diff options
99 files changed, 3573 insertions, 3708 deletions
diff --git a/usr/src/cmd/smbsrv/smbd/smbd.h b/usr/src/cmd/smbsrv/smbd/smbd.h index b3d448381e..a069d6ab4e 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd.h +++ b/usr/src/cmd/smbsrv/smbd/smbd.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -40,6 +40,7 @@ extern "C" { extern int smb_nicmon_start(void); extern void smb_nicmon_stop(void); +extern void smb_nicmon_reconfig(void); extern int smb_winpipe_doorsvc_start(void); extern void smb_winpipe_doorsvc_stop(void); extern int smb_lmshrd_srv_start(void); diff --git a/usr/src/cmd/smbsrv/smbd/smbd_join.c b/usr/src/cmd/smbsrv/smbd/smbd_join.c index 5e7d76396b..7cd50ed347 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_join.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_join.c @@ -43,13 +43,6 @@ #include <smbsrv/lsalib.h> /* - * Local protocol flags used to indicate which version of the - * netlogon protocol to use when attempting to find the PDC. - */ -#define NETLOGON_PROTO_NETLOGON 0x01 -#define NETLOGON_PROTO_SAMLOGON 0x02 - -/* * Maximum time to wait for a domain controller (30 seconds). */ #define SMB_NETLOGON_TIMEOUT 30 @@ -121,8 +114,16 @@ smbd_join(smb_joininfo_t *info) "host principal."); } } + + (void) smb_config_getstr(SMB_CI_DOMAIN_NAME, nbt_domain, + sizeof (nbt_domain)); + (void) smb_config_set_secmode(info->mode); (void) smb_config_setstr(SMB_CI_DOMAIN_NAME, info->domain_name); + + if (strcasecmp(nbt_domain, info->domain_name)) + smb_browser_reconfig(); + return (NT_STATUS_SUCCESS); } @@ -299,8 +300,6 @@ smb_netlogon_dc_browser(void *arg) { boolean_t rc; char resource_domain[SMB_PI_MAX_DOMAIN]; - int net, smb_nc_cnt; - int protocol; for (;;) { (void) mutex_lock(&smb_netlogon_info.snli_locate_mtx); @@ -318,16 +317,8 @@ smb_netlogon_dc_browser(void *arg) smb_setdomaininfo(NULL, NULL, 0); if (msdcs_lookup_ads(resource_domain) == 0) { - if (smb_config_getbool(SMB_CI_DOMAIN_MEMB)) - protocol = NETLOGON_PROTO_SAMLOGON; - else - protocol = NETLOGON_PROTO_NETLOGON; - - smb_nc_cnt = smb_nic_get_num(); - for (net = 0; net < smb_nc_cnt; net++) { - smb_netlogon_request(net, protocol, - resource_domain); - } + /* Try to locate a DC via NetBIOS */ + smb_browser_netlogon(resource_domain); } rc = smb_ntdomain_is_valid(SMB_NETLOGON_TIMEOUT); diff --git a/usr/src/cmd/smbsrv/smbd/smbd_main.c b/usr/src/cmd/smbsrv/smbd/smbd_main.c index ca10cabb19..b407f7bbb0 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_main.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c @@ -66,9 +66,6 @@ #define SMB_CCACHE SMB_VARRUN_DIR "/ccache" #define SMB_DBDIR "/var/smb" -extern void smb_netbios_name_reconfig(); -extern void smb_browser_config(); - static int smbd_daemonize_init(void); static void smbd_daemonize_fini(int, int); @@ -439,6 +436,9 @@ smbd_service_init(void) } (void) smb_lgrp_start(); + + (void) smb_pwd_init(); + return (lmshare_start()); } @@ -469,6 +469,7 @@ smbd_service_fini(void) smb_idmap_stop(); smb_lgrp_stop(); smbd_remove_ccache(); + smb_pwd_fini(); } @@ -534,9 +535,7 @@ smbd_refresh_monitor(void *arg) * what is necessary. */ ads_refresh(); - smb_nic_build_info(); - (void) smb_netbios_name_reconfig(); - (void) smb_browser_config(); + smb_nicmon_reconfig(); smbd_remove_ccache(); if (ioctl(smbd.s_drv_fd, SMB_IOC_CONFIG, &dummy) < 0) { smbd_report("configuration update ioctl: %s", diff --git a/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c index 9f676d1d51..7b44ead3af 100755 --- a/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c @@ -23,6 +23,7 @@ * Use is subject to license terms. */ + #pragma ident "%Z%%M% %I% %E% SMI" #include <stdio.h> @@ -228,21 +229,28 @@ smb_winpipe_request(void *cookie, char *argp, size_t arg_size, inpipe->sp_datalen = context->inlen; context->inlen = 0; - context->outcookie = 0; context->outlen = outpipe->sp_datalen; } - if (mdhin.md_call_type == SMB_RPC_TRANSACT) { - bcopy(bufp, inpipe->sp_data, tmp_pipe.sp_datalen); - inpipe->sp_datalen = tmp_pipe.sp_datalen; - + /* + * Append trans data to the pipe + */ + if ((tmp_pipe.sp_datalen + + context->inlen) > SMB_CTXT_PIPE_SZ) { + context->inlen = 0; + goto zero_exit; + } + bcopy(bufp, inpipe->sp_data + context->inlen, + tmp_pipe.sp_datalen); + inpipe->sp_datalen += tmp_pipe.sp_datalen; context = mlrpc_process(inpipe->sp_pipeid, user_ctx); if (context == NULL) goto zero_exit; context->outcookie = 0; context->outlen = outpipe->sp_datalen; + context->inlen = 0; if (outpipe->sp_datalen < mdhin.md_length) adj_len = outpipe->sp_datalen; if (outpipe->sp_datalen > mdhin.md_length) @@ -252,8 +260,13 @@ smb_winpipe_request(void *cookie, char *argp, size_t arg_size, if (mdhin.md_call_type == SMB_RPC_WRITE) { /* - * Append write data to the stream. + * Append write data to the pipe */ + if ((tmp_pipe.sp_datalen + + context->inlen) > SMB_CTXT_PIPE_SZ) { + context->inlen = 0; + goto zero_exit; + } bcopy(bufp, inpipe->sp_data + context->inlen, tmp_pipe.sp_datalen); inpipe->sp_datalen += tmp_pipe.sp_datalen; diff --git a/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c b/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c index 11a228da07..7a739476b1 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c @@ -49,11 +49,10 @@ static pthread_t smb_nicmon_thread; -static void smb_setup_rtsock(int, int *); -static int smb_nics_changed(int); -static void *smb_nicmonitor(void *); -static int smb_setup_eventpipe(int *, int *); -static void smb_process_nic_change(); +static void smb_nicmon_setup_rtsock(int, int *); +static int smb_nicmon_needscan(int); +static void *smb_nicmon_daemon(void *); +static int smb_nicmon_setup_eventpipe(int *, int *); /* Use this to stop monitoring */ static int eventpipe_write = -1; @@ -66,13 +65,19 @@ smb_nicmon_start(void) { int rc = 0; - smb_nic_build_info(); - rc = pthread_create(&smb_nicmon_thread, NULL, smb_nicmonitor, 0); + if ((rc = smb_nic_init()) != 0) { + syslog(LOG_ERR, "NIC monitor failed to initialize (%s)", + strerror(errno)); + return (rc); + } + + rc = pthread_create(&smb_nicmon_thread, NULL, smb_nicmon_daemon, 0); if (rc != 0) { - syslog(LOG_ERR, "smb_nicmonitor: " - "NIC monitoring failed to start: %s", strerror(errno)); + syslog(LOG_ERR, "NIC monitor failed to start (%s)", + strerror(errno)); return (rc); } + return (rc); } @@ -88,30 +93,67 @@ smb_nicmon_stop(void) return; (void) write(eventpipe_write, &buf, sizeof (buf)); + smb_nic_fini(); +} + +/* + * Call this to do stuff after ifs changed. + */ +void +smb_nicmon_reconfig(void) +{ + boolean_t ddns_enabled; + + ddns_enabled = smb_config_getbool(SMB_CI_DYNDNS_ENABLE); + + /* Clear rev zone before creating if list */ + if (ddns_enabled) { + if (dyndns_clear_rev_zone() != 0) { + syslog(LOG_ERR, "smb_nicmon_daemon: " + "failed to clear DNS reverse lookup zone"); + } + } + + /* re-initialize NIC table */ + if (smb_nic_init() != 0) + syslog(LOG_ERR, "smb_nicmon_daemon: " + "failed to get NIC information"); + + smb_netbios_name_reconfig(); + smb_browser_reconfig(); + + if (ddns_enabled) { + if (dyndns_update() != 0) { + syslog(LOG_ERR, "smb_nicmon_daemon: " + "failed to update dynamic DNS"); + } + } } /* * Setup routing socket for getting RTM messages. */ static void -smb_setup_rtsock(int af, int *s) +smb_nicmon_setup_rtsock(int af, int *s) { int flags; *s = socket(PF_ROUTE, SOCK_RAW, af); if (*s == -1) { - syslog(LOG_ERR, "smb_setup_rtsock: failed to " + syslog(LOG_ERR, "smb_nicmon_daemon: failed to " "create routing socket"); return; } if ((flags = fcntl(*s, F_GETFL, 0)) < 0) { - syslog(LOG_ERR, "smb_setup_rtsock: failed to fcntl F_GETFL"); + syslog(LOG_ERR, "smb_nicmon_daemon: " + "failed to fcntl F_GETFL"); (void) close(*s); *s = -1; return; } if ((fcntl(*s, F_SETFL, flags | O_NONBLOCK)) < 0) { - syslog(LOG_ERR, "smb_setup_rtsock: failed to fcntl F_SETFL"); + syslog(LOG_ERR, "smb_nicmon_daemon: " + "failed to fcntl F_SETFL"); (void) close(*s); *s = -1; return; @@ -119,7 +161,7 @@ smb_setup_rtsock(int af, int *s) } static int -smb_nics_changed(int sock) +smb_nicmon_needscan(int sock) { int nbytes; int64_t msg[2048 / 8]; @@ -137,7 +179,7 @@ smb_nics_changed(int sock) continue; } if (nbytes < rtm->rtm_msglen) { - syslog(LOG_DEBUG, "smb_nicmonitor: short read: %d " + syslog(LOG_DEBUG, "smb_nicmon_daemon: short read: %d " "of %d", nbytes, rtm->rtm_msglen); continue; } @@ -160,12 +202,12 @@ smb_nics_changed(int sock) * Create pipe for signal delivery and set up signal handlers. */ static int -smb_setup_eventpipe(int *read_pipe, int *write_pipe) +smb_nicmon_setup_eventpipe(int *read_pipe, int *write_pipe) { int fds[2]; if ((pipe(fds)) < 0) { - syslog(LOG_ERR, "smb_nicmonitor: failed to open pipe"); + syslog(LOG_ERR, "smb_nicmon_daemon: failed to open pipe"); return (1); } *read_pipe = fds[0]; @@ -173,41 +215,9 @@ smb_setup_eventpipe(int *read_pipe, int *write_pipe) return (0); } -/* - * Call this to do stuff after ifs changed. - */ -static void -smb_process_nic_change() -{ - boolean_t ddns_enabled; - - ddns_enabled = smb_config_getbool(SMB_CI_DYNDNS_ENABLE); - - /* Clear rev zone before creating if list */ - if (ddns_enabled) { - if (dyndns_clear_rev_zone() != 0) { - syslog(LOG_ERR, "smb_nicmonitor: " - "failed to clear DNS reverse lookup zone"); - } - } - - /* re-initialize NIC table */ - smb_nic_build_info(); - - smb_netbios_name_reconfig(); - smb_browser_config(); - - if (ddns_enabled) { - if (dyndns_update() != 0) { - syslog(LOG_ERR, "smb_nicmonitor: " - "failed to update dynamic DNS"); - } - } -} - /*ARGSUSED*/ static void * -smb_nicmonitor(void *args) +smb_nicmon_daemon(void *args) { struct pollfd pollfds[2]; int pollfd_num = 2; @@ -221,13 +231,16 @@ smb_nicmonitor(void *args) * monitor changes in NIC interfaces. We are only interested * in new inerface addition/deletion and change in UP/DOWN status. */ - smb_setup_rtsock(AF_INET, &rtsock_v4); + smb_nicmon_setup_rtsock(AF_INET, &rtsock_v4); if (rtsock_v4 == -1) { - syslog(LOG_ERR, "smb_nicmonitor: cannot open routing socket"); + syslog(LOG_ERR, "smb_nicmon_daemon: " + "cannot open routing socket"); return (NULL); } - if (smb_setup_eventpipe(&eventpipe_read, &eventpipe_write) != 0) { - syslog(LOG_ERR, "smb_nicmonitor: cannot open event pipes"); + + if (smb_nicmon_setup_eventpipe(&eventpipe_read, &eventpipe_write) + != 0) { + syslog(LOG_ERR, "smb_nicmon_daemon: cannot open event pipes"); return (NULL); } @@ -243,7 +256,7 @@ smb_nicmonitor(void *args) if (poll(pollfds, pollfd_num, -1) < 0) { if (errno == EINTR) continue; - syslog(LOG_ERR, "smb_nicmonitor: " + syslog(LOG_ERR, "smb_nicmon_daemon: " "poll failed with errno %d", errno); break; } @@ -252,7 +265,7 @@ smb_nicmonitor(void *args) !(pollfds[i].revents & POLLIN)) continue; if (pollfds[i].fd == rtsock_v4) - nic_changed = smb_nics_changed(rtsock_v4); + nic_changed = smb_nicmon_needscan(rtsock_v4); if (pollfds[i].fd == eventpipe_read) goto done; } @@ -262,7 +275,7 @@ smb_nicmonitor(void *args) * nic list and other configs. */ if (nic_changed) - smb_process_nic_change(); + smb_nicmon_reconfig(); } done: /* Close sockets */ diff --git a/usr/src/lib/libshare/smb/libshare_smb.c b/usr/src/lib/libshare/smb/libshare_smb.c index 1b1fa9baf5..c73abfa732 100644 --- a/usr/src/lib/libshare/smb/libshare_smb.c +++ b/usr/src/lib/libshare/smb/libshare_smb.c @@ -293,6 +293,25 @@ smb_isautoenable(void) } /* + * smb_ismaint() + * + * Determine if the SMF service instance is in the disabled state or + * not. A number of operations depend on this state. + */ +static boolean_t +smb_ismaint(void) +{ + char *str; + boolean_t ret = B_FALSE; + + if ((str = smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI)) != NULL) { + ret = (strcmp(str, SCF_STATE_STRING_MAINT) == 0); + free(str); + } + return (ret); +} + +/* * smb_enable_share tells the implementation that it is to enable the share. * This entails converting the path and options into the appropriate ioctl * calls. It is assumed that all error checking of paths, etc. were @@ -361,7 +380,7 @@ smb_enable_share(sa_share_t share) * For now, it is OK to not be able to enable * the service. */ - if (err == SA_BUSY) + if (err == SA_BUSY || err == SA_SYSTEM_ERR) err = SA_OK; } else { online = B_TRUE; @@ -1233,7 +1252,16 @@ smb_enable_service(void) if (smb_isonline()) { ret = SA_OK; break; + } else if (smb_ismaint()) { + /* maintenance requires help */ + ret = SA_SYSTEM_ERR; + break; + } else if (smb_isdisabled()) { + /* disabled is ok */ + ret = SA_OK; + break; } else { + /* try another time */ ret = SA_BUSY; (void) sleep(1); } diff --git a/usr/src/lib/pam_modules/smb/smb_passwd.c b/usr/src/lib/pam_modules/smb/smb_passwd.c index 9167d093a6..4e484251e3 100644 --- a/usr/src/lib/pam_modules/smb/smb_passwd.c +++ b/usr/src/lib/pam_modules/smb/smb_passwd.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -145,8 +145,12 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) return (PAM_SYSTEM_ERR); } + smb_pwd_init(); + res = smb_pwd_setpasswd(user, newpw); + smb_pwd_fini(); + /* * now map the various return states to user messages * and PAM return codes. diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c index a1f203c09c..656bda3cf8 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c @@ -55,7 +55,6 @@ static unsigned long mlrpc_frag_size = MLRPC_FRAG_SZ; /* * Context table. */ -#define CTXT_PIPE_SZ 65536 #define CTXT_TABLE_ENTRIES 128 static struct mlsvc_rpc_context context_table[CTXT_TABLE_ENTRIES]; static mutex_t mlrpc_context_lock; @@ -167,8 +166,8 @@ mlrpc_lookup(int fid) if (available) { bzero(available, sizeof (struct mlsvc_rpc_context)); - available->inpipe = malloc(CTXT_PIPE_SZ); - available->outpipe = malloc(CTXT_PIPE_SZ); + available->inpipe = malloc(SMB_CTXT_PIPE_SZ); + available->outpipe = malloc(SMB_CTXT_PIPE_SZ); if (available->inpipe == NULL || available->outpipe == NULL) { free(available->inpipe); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c index 0bc4206f3d..7820c47593 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c @@ -313,7 +313,7 @@ lsarpc_s_OpenAccount(void *arg, struct mlrpc_xaction *mxa) hd = ndr_hdlookup(mxa, id); if ((hd == NULL) || (hd->nh_data != &lsarpc_key_domain)) { - bzero(¶m, sizeof (struct mslsa_OpenAccount)); + bzero(param, sizeof (struct mslsa_OpenAccount)); param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_svcctl.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_svcctl.c index 242fdbc75f..0b44de942f 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_svcctl.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_svcctl.c @@ -255,7 +255,7 @@ svcctl_s_QueryServiceStatus(void *arg, struct mlrpc_xaction *mxa) hd = ndr_hdlookup(mxa, id); if ((hd == NULL) || (hd->nh_data != &svcctl_key_service)) { - bzero(¶m, sizeof (struct svcctl_QueryServiceStatus)); + bzero(param, sizeof (struct svcctl_QueryServiceStatus)); param->status = ERROR_INVALID_HANDLE; return (MLRPC_DRC_OK); } @@ -298,7 +298,7 @@ svcctl_s_EnumServicesStatus(void *arg, struct mlrpc_xaction *mxa) hd = ndr_hdlookup(mxa, id); if ((hd == NULL) || (hd->nh_data != &svcctl_key_manager)) { - bzero(¶m, sizeof (struct svcctl_EnumServicesStatus)); + bzero(param, sizeof (struct svcctl_EnumServicesStatus)); param->status = ERROR_INVALID_HANDLE; return (MLRPC_DRC_OK); } @@ -371,7 +371,7 @@ svcctl_s_QueryServiceConfig(void *arg, struct mlrpc_xaction *mxa) hd = ndr_hdlookup(mxa, id); if ((hd == NULL) || (hd->nh_data != &svcctl_key_service)) { - bzero(¶m, sizeof (struct svcctl_QueryServiceConfig)); + bzero(param, sizeof (struct svcctl_QueryServiceConfig)); param->status = ERROR_INVALID_HANDLE; return (MLRPC_DRC_OK); } diff --git a/usr/src/lib/smbsrv/libsmb/Makefile.com b/usr/src/lib/smbsrv/libsmb/Makefile.com index 857605eb72..7573c93e12 100644 --- a/usr/src/lib/smbsrv/libsmb/Makefile.com +++ b/usr/src/lib/smbsrv/libsmb/Makefile.com @@ -59,8 +59,10 @@ OBJS_COMMON = \ smb_ht.o \ smb_idmap.o \ smb_info.o \ + smb_list.o \ smb_lgrp.o \ smb_mac.o \ + smb_nic.o \ smb_pwdutil.o \ smb_privilege.o \ smb_scfutil.o \ @@ -76,7 +78,7 @@ include ../../Makefile.lib INCS += -I$(SRC)/common/smbsrv LDLIBS += $(MACH_LDLIBS) -LDLIBS += -lscf -lmd -lnsl -lpkcs11 -lc -lresolv -lidmap +LDLIBS += -lscf -lmd -lnsl -lpkcs11 -lc -lsocket -lresolv -lidmap CPPFLAGS += $(INCS) -D_REENTRANT SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \ diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h index 50a3c3d989..b6232a5844 100644 --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h @@ -33,7 +33,9 @@ extern "C" { #endif #include <sys/types.h> +#include <sys/list.h> #include <arpa/inet.h> +#include <net/if.h> #include <netdb.h> #include <stdlib.h> @@ -43,6 +45,7 @@ extern "C" { #include <smbsrv/string.h> #include <smbsrv/smb_idmap.h> +#include <smbsrv/netbios.h> /* * XXX - These header files are here, only because other libraries @@ -280,6 +283,10 @@ extern int smb_gethostname(char *, size_t, int); extern int smb_getfqhostname(char *, size_t); extern int smb_getnetbiosname(char *, size_t); +extern int smb_get_nameservers(struct in_addr *, int); +extern void smb_tonetbiosname(char *, char *, char); + + void smb_trace(const char *s); void smb_tracef(const char *fmt, ...); @@ -430,6 +437,8 @@ typedef struct smb_passwd { #define SMB_PWE_SYSTEM_ERROR 11 #define SMB_PWE_MAX 12 +extern void smb_pwd_init(void); +extern void smb_pwd_fini(void); extern smb_passwd_t *smb_pwd_getpasswd(const char *, smb_passwd_t *); extern int smb_pwd_setpasswd(const char *, const char *); extern int smb_pwd_setcntl(const char *, int); @@ -665,6 +674,45 @@ int smb_lookup_name(char *, smb_gsid_t *); #define SMB_LGRP_COMMENT_MAX 256 #define SMB_LGRP_NAME_MAX (SMB_LGRP_NAME_CHAR_MAX * MTS_MB_CHAR_MAX + 1) +/* + * values for smb_nic_t.smbflags + */ +#define SMB_NICF_NBEXCL 0x01 /* Excluded from Netbios activities */ +#define SMB_NICF_ALIAS 0x02 /* This is an alias */ + +/* + * smb_nic_t + * nic_host actual host name + * nic_nbname 16-byte NetBIOS host name + */ +typedef struct { + char nic_host[MAXHOSTNAMELEN]; + char nic_nbname[NETBIOS_NAME_SZ]; + char nic_cmnt[SMB_PI_MAX_COMMENT]; + char nic_ifname[LIFNAMSIZ]; + uint32_t nic_ip; + uint32_t nic_mask; + uint32_t nic_bcast; + uint32_t nic_smbflags; + uint64_t nic_sysflags; +} smb_nic_t; + +typedef struct smb_niciter { + smb_nic_t ni_nic; + int ni_cookie; + int ni_seqnum; +} smb_niciter_t; + +/* NIC config functions */ +int smb_nic_init(void); +void smb_nic_fini(void); +int smb_nic_getnum(char *); +int smb_nic_addhost(const char *, const char *, int, const char **); +int smb_nic_delhost(const char *); +int smb_nic_getfirst(smb_niciter_t *); +int smb_nic_getnext(smb_niciter_t *); +boolean_t smb_nic_exists(uint32_t, boolean_t); + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers index 20d808c588..7efbabcaec 100644 --- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers @@ -48,6 +48,20 @@ SUNWprivate { ht_remove_item; ht_replace_item; ht_set_cmpfn; + list_create; + list_destroy; + list_head; + list_insert_after; + list_insert_before; + list_insert_head; + list_insert_tail; + list_is_empty; + list_link_active; + list_move_tail; + list_next; + list_prev; + list_remove; + list_tail; smb_msgbuf_base; smb_msgbuf_decode; smb_msgbuf_dword_align; @@ -184,6 +198,7 @@ SUNWprivate { smb_dwncall_install_callback; smb_dwncall_share; smb_dwncall_user_num; + smb_get_nameservers; smb_getdomaininfo; smb_getdomainname; smb_getfqdomainname; @@ -233,6 +248,14 @@ SUNWprivate { smb_match83; smb_match; smb_match_ci; + smb_nic_addhost; + smb_nic_delhost; + smb_nic_exists; + smb_nic_fini; + smb_nic_getfirst; + smb_nic_getnext; + smb_nic_getnum; + smb_nic_init; smb_priv_getbyname; smb_priv_getbyvalue; smb_priv_presentable_ids; @@ -247,11 +270,14 @@ SUNWprivate { smb_privset_query; smb_privset_size; smb_privset_validate; + smb_tonetbiosname; smb_trace; smb_tracef; - smb_pwd_getpasswd; - smb_pwd_setcntl; - smb_pwd_setpasswd; + smb_pwd_fini; + smb_pwd_getpasswd = AUXILIARY libsmb_pwd.so; + smb_pwd_init; + smb_pwd_setcntl = AUXILIARY libsmb_pwd.so; + smb_pwd_setpasswd = AUXILIARY libsmb_pwd.so; smb_resolve_fqdn; smb_resolve_netbiosname; smb_setdomaininfo; diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_info.c b/usr/src/lib/smbsrv/libsmb/common/smb_info.c index 918cc02acb..0bc21f71a0 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_info.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_info.c @@ -440,3 +440,65 @@ smb_trace(const char *s) { syslog(LOG_DEBUG, "%s", s); } + +/* + * smb_tonetbiosname + * + * Creates a NetBIOS name based on the given name and suffix. + * NetBIOS name is 15 capital characters, padded with space if needed + * and the 16th byte is the suffix. + */ +void +smb_tonetbiosname(char *name, char *nb_name, char suffix) +{ + char tmp_name[NETBIOS_NAME_SZ]; + mts_wchar_t wtmp_name[NETBIOS_NAME_SZ]; + unsigned int cpid; + int len; + size_t rc; + + len = 0; + rc = mts_mbstowcs(wtmp_name, (const char *)name, NETBIOS_NAME_SZ); + + if (rc != (size_t)-1) { + wtmp_name[NETBIOS_NAME_SZ - 1] = 0; + cpid = oem_get_smb_cpid(); + rc = unicodestooems(tmp_name, wtmp_name, NETBIOS_NAME_SZ, cpid); + if (rc > 0) + len = strlen(tmp_name); + } + + (void) memset(nb_name, ' ', NETBIOS_NAME_SZ - 1); + if (len) { + (void) utf8_strupr(tmp_name); + (void) memcpy(nb_name, tmp_name, len); + } + nb_name[NETBIOS_NAME_SZ - 1] = suffix; +} + +int +smb_get_nameservers(struct in_addr *ips, int sz) +{ + union res_sockaddr_union set[MAXNS]; + int i, cnt; + struct __res_state res_state; + + if (ips == NULL) + return (0); + + bzero(&res_state, sizeof (struct __res_state)); + if (res_ninit(&res_state) < 0) + return (0); + + cnt = res_getservers(&res_state, set, MAXNS); + for (i = 0; i < cnt; i++) { + if (i >= sz) + break; + ips[i] = set[i].sin.sin_addr; + syslog(LOG_DEBUG, "NS Found %s name server\n", + inet_ntoa(ips[i])); + } + syslog(LOG_DEBUG, "NS Found %d name servers\n", i); + res_ndestroy(&res_state); + return (i); +} diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c b/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c index 934b804dcd..f363bc9a32 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c @@ -35,6 +35,7 @@ #include <assert.h> #include <libintl.h> #include <smbsrv/libsmb.h> +#include <smb_sqlite.h> #define SMB_LGRP_LOCAL_IDX 0 #define SMB_LGRP_BUILTIN_IDX 1 @@ -177,97 +178,6 @@ static boolean_t smb_lgrp_chkname(char *); static boolean_t smb_lgrp_chkmember(uint16_t); static int smb_lgrp_getsid(int, uint32_t *, uint16_t, sqlite *, nt_sid_t **); -#ifdef _LP64 -/* - * We cannot make 64-bit version of libsqlite because the code - * has some problems. - */ - -/*ARGSUSED*/ -sqlite * -sqlite_open(const char *filename, int mode, char **errmsg) -{ - return (NULL); -} - -/*ARGSUSED*/ -void -sqlite_close(sqlite *db) -{ -} - -/*ARGSUSED*/ -char * -sqlite_mprintf(const char *fmt, ...) -{ - return (NULL); -} - -/*ARGSUSED*/ -void -sqlite_freemem(void *p) -{ -} - -/*ARGSUSED*/ -int -sqlite_compile(sqlite *db, const char *zSql, const char **pzTail, - sqlite_vm **ppVm, char **pzErrmsg) -{ - return (SQLITE_ERROR); -} - -/*ARGSUSED*/ -void -sqlite_free_table(char **res) -{ -} - -/*ARGSUSED*/ -int -sqlite_last_insert_rowid(sqlite *db) -{ - return (-1); -} - -/*ARGSUSED*/ -void -sqlite_busy_timeout(sqlite *db, int ms) -{ -} - -/*ARGSUSED*/ -int -sqlite_get_table(sqlite *db, const char *zSql, char ***pazResult, int *pnRow, - int *pnColumn, char **pzErrMsg) -{ - return (SQLITE_ERROR); -} - -/*ARGSUSED*/ -int -sqlite_step(sqlite_vm *pVm, int *pN, const char ***pazValue, - const char ***pazColName) -{ - return (SQLITE_ERROR); -} - -/*ARGSUSED*/ -int -sqlite_exec(sqlite *db, const char *zSql, sqlite_callback xCallback, void *pArg, - char **pzErrMsg) -{ - return (SQLITE_ERROR); -} - -/*ARGSUSED*/ -int -sqlite_finalize(sqlite_vm *pVm, char **pzErrMsg) -{ - return (SQLITE_ERROR); -} -#endif /* _LP64 */ - /* * smb_lgrp_add * diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_list.c b/usr/src/lib/smbsrv/libsmb/common/smb_list.c new file mode 100644 index 0000000000..db891ffb2f --- /dev/null +++ b/usr/src/lib/smbsrv/libsmb/common/smb_list.c @@ -0,0 +1,195 @@ +/* + * 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 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Generic doubly-linked list implementation + */ + +#include <sys/list.h> +#include <sys/list_impl.h> +#include <sys/types.h> +#include <sys/sysmacros.h> +#include <sys/debug.h> +#include <assert.h> + +#define list_d2l(a, obj) ((void *)(((char *)obj) + (a)->list_offset)) +#define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset)) +#define list_empty(a) ((a)->list_head.list_next == &(a)->list_head) + +#define list_insert_after_node(list, node, object) { \ + list_node_t *lnew = list_d2l(list, object); \ + lnew->list_prev = node; \ + lnew->list_next = node->list_next; \ + node->list_next->list_prev = lnew; \ + node->list_next = lnew; \ +} + +#define list_insert_before_node(list, node, object) { \ + list_node_t *lnew = list_d2l(list, object); \ + lnew->list_next = node; \ + lnew->list_prev = node->list_prev; \ + node->list_prev->list_next = lnew; \ + node->list_prev = lnew; \ +} + +void +list_create(list_t *list, size_t size, size_t offset) +{ + assert(list); + assert(size > 0); + assert(size >= offset + sizeof (list_node_t)); + + list->list_size = size; + list->list_offset = offset; + list->list_head.list_next = list->list_head.list_prev = + &list->list_head; +} + +void +list_destroy(list_t *list) +{ + list_node_t *node = &list->list_head; + + assert(list); + assert(list->list_head.list_next == node); + assert(list->list_head.list_prev == node); + + node->list_next = node->list_prev = NULL; +} + +void +list_insert_after(list_t *list, void *object, void *nobject) +{ + list_node_t *lold = list_d2l(list, object); + list_insert_after_node(list, lold, nobject); +} + +void +list_insert_before(list_t *list, void *object, void *nobject) +{ + list_node_t *lold = list_d2l(list, object); + list_insert_before_node(list, lold, nobject) +} + +void +list_insert_head(list_t *list, void *object) +{ + list_node_t *lold = &list->list_head; + list_insert_after_node(list, lold, object); +} + +void +list_insert_tail(list_t *list, void *object) +{ + list_node_t *lold = &list->list_head; + list_insert_before_node(list, lold, object); +} + +void +list_remove(list_t *list, void *object) +{ + list_node_t *lold = list_d2l(list, object); + assert(!list_empty(list)); + assert(lold->list_next != NULL); + lold->list_prev->list_next = lold->list_next; + lold->list_next->list_prev = lold->list_prev; + lold->list_next = lold->list_prev = NULL; +} + +void * +list_head(list_t *list) +{ + if (list_empty(list)) + return (NULL); + return (list_object(list, list->list_head.list_next)); +} + +void * +list_tail(list_t *list) +{ + if (list_empty(list)) + return (NULL); + return (list_object(list, list->list_head.list_prev)); +} + +void * +list_next(list_t *list, void *object) +{ + list_node_t *node = list_d2l(list, object); + + if (node->list_next != &list->list_head) + return (list_object(list, node->list_next)); + + return (NULL); +} + +void * +list_prev(list_t *list, void *object) +{ + list_node_t *node = list_d2l(list, object); + + if (node->list_prev != &list->list_head) + return (list_object(list, node->list_prev)); + + return (NULL); +} + +/* + * Insert src list after dst list. Empty src list thereafter. + */ +void +list_move_tail(list_t *dst, list_t *src) +{ + list_node_t *dstnode = &dst->list_head; + list_node_t *srcnode = &src->list_head; + + assert(dst->list_size == src->list_size); + assert(dst->list_offset == src->list_offset); + + if (list_empty(src)) + return; + + dstnode->list_prev->list_next = srcnode->list_next; + srcnode->list_next->list_prev = dstnode->list_prev; + dstnode->list_prev = srcnode->list_prev; + srcnode->list_prev->list_next = dstnode; + + /* empty src list */ + srcnode->list_next = srcnode->list_prev = srcnode; +} + +int +list_link_active(list_node_t *link) +{ + return (link->list_next != NULL); +} + +int +list_is_empty(list_t *list) +{ + return (list_empty(list)); +} diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_nic.c b/usr/src/lib/smbsrv/libsmb/common/smb_nic.c new file mode 100644 index 0000000000..2799df5697 --- /dev/null +++ b/usr/src/lib/smbsrv/libsmb/common/smb_nic.c @@ -0,0 +1,1080 @@ +/* + * 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 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <syslog.h> +#include <libintl.h> +#include <strings.h> +#include <string.h> +#include <unistd.h> +#include <synch.h> +#include <stropts.h> +#include <errno.h> +#include <pthread.h> + +#include <inet/ip.h> +#include <net/if.h> +#include <netinet/in.h> +#include <netdb.h> +#include <net/route.h> +#include <arpa/inet.h> + +#include <sys/socket.h> +#include <sys/sockio.h> +#include <sys/systeminfo.h> + +#include <smbsrv/libsmb.h> + +#define SMB_NIC_DB_NAME "/var/smb/smbhosts.db" +#define SMB_NIC_DB_TIMEOUT 3000 /* in millisecond */ +#define SMB_NIC_DB_VERMAJOR 1 +#define SMB_NIC_DB_VERMINOR 0 +#define SMB_NIC_DB_MAGIC 0x484F5354 /* HOST */ + +#define SMB_NIC_DB_ORD 1 /* open read-only */ +#define SMB_NIC_DB_ORW 2 /* open read/write */ + +#define SMB_NIC_DB_SQL \ + "CREATE TABLE db_info (" \ + " ver_major INTEGER," \ + " ver_minor INTEGER," \ + " magic INTEGER" \ + ");" \ + "" \ + "CREATE TABLE hosts (" \ + " hostname TEXT PRIMARY KEY," \ + " comment TEXT," \ + " ifnames TEXT" \ + ");" + +#define SMB_NIC_HTBL_NCOL 3 +#define SMB_NIC_HTBL_HOST 0 +#define SMB_NIC_HTBL_CMNT 1 +#define SMB_NIC_HTBL_IFS 2 + +#define NULL_MSGCHK(msg) ((msg) ? (msg) : "NULL") + +#define SMB_NIC_MAXIFS 256 + +typedef struct smb_hostifs { + list_node_t if_lnd; + char if_host[MAXHOSTNAMELEN]; + char if_cmnt[SMB_PI_MAX_COMMENT]; + char *if_names[SMB_NIC_MAXIFS]; + int if_num; +} smb_hostifs_t; + +typedef struct smb_hosts { + list_t h_list; + int h_num; + int h_ifnum; +} smb_hosts_t; + +typedef struct { + smb_nic_t *nl_nics; + int nl_cnt; /* number of smb_nic_t structures */ + int nl_hcnt; /* number of host names */ + long nl_seqnum; /* a random sequence number */ + rwlock_t nl_rwl; +} smb_niclist_t; + +static int smb_nic_list_create(void); +static void smb_nic_list_destroy(void); + +static int smb_nic_hlist_create(smb_hosts_t *); +static void smb_nic_hlist_destroy(smb_hosts_t *); +static int smb_nic_hlist_dbget(smb_hosts_t *); +static int smb_nic_hlist_sysget(smb_hosts_t *); + +static void smb_nic_iflist_destroy(smb_hostifs_t *); +static smb_hostifs_t *smb_nic_iflist_decode(const char **); + +static int smb_nic_dbcreate(void); +static sqlite *smb_nic_dbopen(int); +static void smb_nic_dbclose(sqlite *); +static boolean_t smb_nic_dbexists(void); +static boolean_t smb_nic_dbvalidate(void); +static int smb_nic_dbaddhost(const char *, const char *, char *); +static int smb_nic_dbdelhost(const char *); +static int smb_nic_dbsetinfo(sqlite *); + +static int smb_nic_getinfo(char *, smb_nic_t *); + +/* This is the list we will monitor */ +static smb_niclist_t smb_niclist; + +/* + * smb_nic_init + * + * Initializes the interface list. + */ +int +smb_nic_init(void) +{ + int rc; + + (void) rw_wrlock(&smb_niclist.nl_rwl); + smb_nic_list_destroy(); + rc = smb_nic_list_create(); + (void) rw_unlock(&smb_niclist.nl_rwl); + + return (rc); +} + +/* + * smb_nic_fini + * + * Destroys the interface list. + */ +void +smb_nic_fini(void) +{ + (void) rw_wrlock(&smb_niclist.nl_rwl); + smb_nic_list_destroy(); + (void) rw_unlock(&smb_niclist.nl_rwl); +} + +/* + * smb_nic_getnum + * + * Gets the number of interfaces for the specified host. + * if host is NULL then total number of interfaces + * is returned. It's assumed that given name is a NetBIOS + * encoded name. + */ +int +smb_nic_getnum(char *nb_hostname) +{ + int n = 0, i; + + (void) rw_rdlock(&smb_niclist.nl_rwl); + + if (nb_hostname != NULL) { + for (i = 0; i < smb_niclist.nl_cnt; i++) { + /* ignore the suffix */ + if (strncasecmp(smb_niclist.nl_nics[i].nic_nbname, + nb_hostname, NETBIOS_NAME_SZ - 1) == 0) + n++; + } + } else { + n = smb_niclist.nl_cnt; + } + + (void) rw_unlock(&smb_niclist.nl_rwl); + + return (n); +} + +/* + * smb_nic_getfirst + * + * Returns the first NIC in the interface list and + * initializes the given iterator. To get the rest of + * NICs smb_nic_getnext() must be called. + * + * Returns 0 upon success and -1 if there's no interface + * available or if 'ni' is NULL. + */ +int +smb_nic_getfirst(smb_niciter_t *ni) +{ + int rc = 0; + + if (ni == NULL) + return (-1); + + (void) rw_rdlock(&smb_niclist.nl_rwl); + + if (smb_niclist.nl_cnt > 0) { + ni->ni_nic = smb_niclist.nl_nics[0]; + ni->ni_cookie = 1; + ni->ni_seqnum = smb_niclist.nl_seqnum; + } else { + rc = -1; + } + + (void) rw_unlock(&smb_niclist.nl_rwl); + + return (rc); +} + +/* + * smb_nic_getnext + * + * Returns the next NIC information based on the passed + * iterator (ni). The iterator must have previously been + * initialized by calling smb_nic_getfirst(). + * + * Returns 0 upon successfully finding the specified NIC. + * Returns -1 if: + * - the specified iterator is invalid + * - reaches the end of the NIC list + * - sequence number in the iterator is different from + * the sequence number in the NIC list which means + * the list has been changed between getfirst/getnext + * calls. + */ +int +smb_nic_getnext(smb_niciter_t *ni) +{ + int rc = 0; + + if ((ni == NULL) || (ni->ni_cookie < 1)) + return (-1); + + (void) rw_rdlock(&smb_niclist.nl_rwl); + + if ((smb_niclist.nl_cnt > ni->ni_cookie) && + (smb_niclist.nl_seqnum == ni->ni_seqnum)) { + ni->ni_nic = smb_niclist.nl_nics[ni->ni_cookie]; + ni->ni_cookie++; + } else { + rc = -1; + } + + (void) rw_unlock(&smb_niclist.nl_rwl); + + return (rc); +} + +/* + * smb_nic_exists + * + * Check to see if there's a NIC with the given IP address + * in the list. Subnet mask will be applied when comparing the + * IPs if the use_mask arg is true. + */ +boolean_t +smb_nic_exists(uint32_t ipaddr, boolean_t use_mask) +{ + smb_nic_t *cfg; + uint32_t mask = 0xFFFFFFFF; + int i; + + (void) rw_rdlock(&smb_niclist.nl_rwl); + + for (i = 0; i < smb_niclist.nl_cnt; i++) { + cfg = &smb_niclist.nl_nics[i]; + if (use_mask) + mask = cfg->nic_mask; + + if ((ipaddr & mask) == (cfg->nic_ip & mask)) { + (void) rw_unlock(&smb_niclist.nl_rwl); + return (B_TRUE); + } + } + + (void) rw_unlock(&smb_niclist.nl_rwl); + + return (B_FALSE); +} + +/* + * smb_nic_addhost + * + * Adds an association between the given host and the specified interface + * list (if_names). This function can be called as many times as needed, + * the associations will be stored in /var/smb/smbhosts.db, which is sqlite + * database. If this file exists and it's not empty NIC list is generated + * based on the information stored in this file. + * + * host: actual system's name (not Netbios name) + * cmnt: an optional description for the CIFS server running on + * the specified host. Can be NULL. + * if_num: number of interface names in if_names arg + * if_names: array of interface names in string format + * + * Returns 0 upon success and -1 when fails + */ +int +smb_nic_addhost(const char *host, const char *cmnt, + int if_num, const char **if_names) +{ + char *if_list; + char *ifname; + int buflen = 0; + int rc, i; + + if ((host == NULL) || (if_num <= 0) || (if_names == NULL)) + return (-1); + + if (!smb_nic_dbexists() || !smb_nic_dbvalidate()) { + if (smb_nic_dbcreate() != SQLITE_OK) + return (-1); + } + + ifname = (char *)if_names; + for (i = 0; i < if_num; i++, ifname++) { + if ((ifname == NULL) || (*ifname == '\0')) + return (-1); + buflen += strlen(ifname) + 1; + } + + if ((if_list = malloc(buflen)) == NULL) + return (-1); + + ifname = if_list; + for (i = 0; i < if_num - 1; i++) + ifname += snprintf(ifname, buflen, "%s,", if_names[i]); + + (void) snprintf(ifname, buflen, "%s", if_names[i]); + + rc = smb_nic_dbaddhost(host, cmnt, if_list); + free(if_list); + + return ((rc == SQLITE_OK) ? 0 : -1); +} + +/* + * smb_nic_delhost + * + * Removes the stored interface association for the specified host + */ +int +smb_nic_delhost(const char *host) +{ + if ((host == NULL) || (*host == '\0')) + return (-1); + + if (!smb_nic_dbexists()) + return (0); + + if (!smb_nic_dbvalidate()) { + (void) unlink(SMB_NIC_DB_NAME); + return (0); + } + + if (smb_nic_dbdelhost(host) != SQLITE_OK) + return (-1); + + return (0); +} + +/* + * smb_nic_list_create + * + * Creates a NIC list either based on /var/smb/smbhosts.db or + * by getting the information from OS. + * + * Note that the caller of this function should grab the + * list lock. + */ +static int +smb_nic_list_create(void) +{ + smb_hosts_t hlist; + smb_hostifs_t *iflist; + smb_nic_t *nc; + char *ifname; + char excludestr[MAX_EXCLUDE_LIST_LEN]; + ipaddr_t exclude[SMB_PI_MAX_NETWORKS]; + int nexclude; + int i; + + if (smb_nic_hlist_create(&hlist) < 0) + return (-1); + + smb_niclist.nl_cnt = 0; + smb_niclist.nl_seqnum = random(); + smb_niclist.nl_hcnt = hlist.h_num; + + smb_niclist.nl_nics = calloc(hlist.h_ifnum, sizeof (smb_nic_t)); + if (smb_niclist.nl_nics == NULL) { + smb_nic_hlist_destroy(&hlist); + return (-1); + } + + (void) smb_config_getstr(SMB_CI_WINS_EXCL, excludestr, + sizeof (excludestr)); + nexclude = smb_wins_iplist(excludestr, exclude, SMB_PI_MAX_NETWORKS); + + nc = smb_niclist.nl_nics; + iflist = list_head(&hlist.h_list); + + do { + for (i = 0; i < iflist->if_num; i++) { + ifname = iflist->if_names[i]; + if (smb_nic_getinfo(ifname, nc) < 0) + continue; + + (void) strlcpy(nc->nic_host, iflist->if_host, + sizeof (nc->nic_host)); + (void) strlcpy(nc->nic_cmnt, iflist->if_cmnt, + sizeof (nc->nic_cmnt)); + + smb_tonetbiosname(nc->nic_host, nc->nic_nbname, 0x00); + + if (strchr(ifname, ':')) + nc->nic_smbflags |= SMB_NICF_ALIAS; + + if (smb_wins_is_excluded(nc->nic_ip, + (ipaddr_t *)exclude, nexclude)) + nc->nic_smbflags |= SMB_NICF_NBEXCL; + + smb_niclist.nl_cnt++; + nc++; + } + } while ((iflist = list_next(&hlist.h_list, iflist)) != NULL); + + smb_nic_hlist_destroy(&hlist); + + if (smb_niclist.nl_cnt == 0) { + smb_nic_list_destroy(); + return (-1); + } + + return (0); +} + +static void +smb_nic_list_destroy(void) +{ + free(smb_niclist.nl_nics); + smb_niclist.nl_nics = NULL; + smb_niclist.nl_cnt = 0; +} + +/* + * smb_nic_getinfo + * + * Get IP info and more for the given interface + */ +static int +smb_nic_getinfo(char *interface, smb_nic_t *nc) +{ + struct lifreq lifrr; + struct sockaddr_in *sa; + int s; + + if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { + return (-1); + } + + (void) strlcpy(lifrr.lifr_name, interface, sizeof (lifrr.lifr_name)); + if (ioctl(s, SIOCGLIFADDR, &lifrr) < 0) { + (void) close(s); + return (-1); + } + sa = (struct sockaddr_in *)&lifrr.lifr_addr; + nc->nic_ip = (uint32_t)sa->sin_addr.s_addr; + + if (nc->nic_ip == 0) { + (void) close(s); + return (-1); + } + + if (ioctl(s, SIOCGLIFBRDADDR, &lifrr) < 0) { + (void) close(s); + return (-1); + } + sa = (struct sockaddr_in *)&lifrr.lifr_broadaddr; + nc->nic_bcast = (uint32_t)sa->sin_addr.s_addr; + + if (ioctl(s, SIOCGLIFNETMASK, &lifrr) < 0) { + (void) close(s); + return (-1); + } + sa = (struct sockaddr_in *)&lifrr.lifr_addr; + nc->nic_mask = (uint32_t)sa->sin_addr.s_addr; + + if (ioctl(s, SIOCGLIFFLAGS, &lifrr) < 0) { + (void) close(s); + return (-1); + } + nc->nic_sysflags = lifrr.lifr_flags; + + (void) strlcpy(nc->nic_ifname, interface, sizeof (nc->nic_ifname)); + + (void) close(s); + return (0); +} + +/* + * smb_nic_hlist_create + * + * Creates a list of hosts and their associated interfaces. + * If host database exists the information is retrieved from + * the database, otherwise it's retrieved from OS. + * + * The allocated memories for the returned list should be freed + * by calling smb_nic_hlist_destroy() + */ +static int +smb_nic_hlist_create(smb_hosts_t *hlist) +{ + int rc; + + list_create(&hlist->h_list, sizeof (smb_hostifs_t), + offsetof(smb_hostifs_t, if_lnd)); + hlist->h_num = 0; + hlist->h_ifnum = 0; + + if (smb_nic_dbexists() && smb_nic_dbvalidate()) { + rc = smb_nic_hlist_dbget(hlist); + errno = EBADF; + } else { + rc = smb_nic_hlist_sysget(hlist); + } + + if (rc != 0) + smb_nic_hlist_destroy(hlist); + + return (rc); +} + +static void +smb_nic_hlist_destroy(smb_hosts_t *hlist) +{ + smb_hostifs_t *iflist; + + if (hlist == NULL) + return; + + while ((iflist = list_head(&hlist->h_list)) != NULL) { + list_remove(&hlist->h_list, iflist); + smb_nic_iflist_destroy(iflist); + } + + list_destroy(&hlist->h_list); +} + +/* + * smb_nic_hlist_sysget + * + * Get the list of currently plumbed and up interface names. The loopback (lo0) + * port is ignored + */ +static int +smb_nic_hlist_sysget(smb_hosts_t *hlist) +{ + smb_hostifs_t *iflist; + struct ifconf ifc; + struct ifreq ifr; + struct ifreq *ifrp; + char *ifname; + int ifnum; + int i; + int s; + + iflist = malloc(sizeof (smb_hostifs_t)); + if (iflist == NULL) + return (-1); + + bzero(iflist, sizeof (smb_hostifs_t)); + + if (smb_gethostname(iflist->if_host, sizeof (iflist->if_host), 0) < 0) { + free(iflist); + return (-1); + } + + (void) smb_config_getstr(SMB_CI_SYS_CMNT, iflist->if_cmnt, + sizeof (iflist->if_cmnt)); + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + free(iflist); + return (-1); + } + + if (ioctl(s, SIOCGIFNUM, (char *)&ifnum) < 0) { + (void) close(s); + free(iflist); + return (-1); + } + + ifc.ifc_len = ifnum * sizeof (struct ifreq); + ifc.ifc_buf = malloc(ifc.ifc_len); + if (ifc.ifc_buf == NULL) { + (void) close(s); + free(iflist); + return (-1); + } + bzero(ifc.ifc_buf, ifc.ifc_len); + + if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { + (void) close(s); + free(iflist); + free(ifc.ifc_buf); + return (-1); + } + + ifrp = ifc.ifc_req; + ifnum = ifc.ifc_len / sizeof (struct ifreq); + + for (i = 0; i < ifnum; i++, ifrp++) { + /* + * Get the flags so that we can skip the loopback interface + */ + (void) memset(&ifr, 0, sizeof (ifr)); + (void) strlcpy(ifr.ifr_name, ifrp->ifr_name, + sizeof (ifr.ifr_name)); + + if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { + (void) close(s); + free(ifc.ifc_buf); + smb_nic_iflist_destroy(iflist); + return (-1); + } + + if (ifr.ifr_flags & IFF_LOOPBACK) + continue; + + if ((ifr.ifr_flags & IFF_UP) == 0) + continue; + + ifname = strdup(ifrp->ifr_name); + if (ifname == NULL) { + (void) close(s); + free(ifc.ifc_buf); + smb_nic_iflist_destroy(iflist); + return (-1); + } + iflist->if_names[iflist->if_num++] = ifname; + } + + (void) close(s); + free(ifc.ifc_buf); + + hlist->h_num = 1; + hlist->h_ifnum = iflist->if_num; + list_insert_tail(&hlist->h_list, iflist); + + return (0); +} + +static int +smb_nic_hlist_dbget(smb_hosts_t *hlist) +{ + smb_hostifs_t *iflist; + sqlite *db; + sqlite_vm *vm; + boolean_t error = B_FALSE; + const char **values; + char *sql; + char *errmsg = NULL; + int ncol, rc; + + sql = sqlite_mprintf("SELECT * FROM hosts"); + if (sql == NULL) + return (-1); + + db = smb_nic_dbopen(SMB_NIC_DB_ORD); + if (db == NULL) { + sqlite_freemem(sql); + return (-1); + } + + rc = sqlite_compile(db, sql, NULL, &vm, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + smb_nic_dbclose(db); + syslog(LOG_DEBUG, "smb_nic_hlist_dbget: failed to create" + " VM (%s)", NULL_MSGCHK(errmsg)); + return (-1); + } + + do { + rc = sqlite_step(vm, &ncol, &values, NULL); + if (rc == SQLITE_ROW) { + if (ncol != SMB_NIC_HTBL_NCOL) { + error = B_TRUE; + break; + } + + if ((iflist = smb_nic_iflist_decode(values)) == NULL) { + error = B_TRUE; + break; + } + + list_insert_tail(&hlist->h_list, iflist); + hlist->h_num++; + hlist->h_ifnum += iflist->if_num; + } + } while (rc == SQLITE_ROW); + + if (rc != SQLITE_DONE) + error = B_TRUE; + + rc = sqlite_finalize(vm, &errmsg); + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "smb_nic_hlist_dbget: failed to destroy" + "VM (%s)", NULL_MSGCHK(errmsg)); + error = B_TRUE; + } + + smb_nic_dbclose(db); + + return ((error) ? -1 : 0); +} + +static smb_hostifs_t * +smb_nic_iflist_decode(const char **values) +{ + smb_hostifs_t *iflist; + char *host; + char *cmnt; + char *ifnames; + char *lasts; + char *ifname; + int if_num = 0; + + host = (char *)values[SMB_NIC_HTBL_HOST]; + cmnt = (char *)values[SMB_NIC_HTBL_CMNT]; + ifnames = (char *)values[SMB_NIC_HTBL_IFS]; + + if ((host == NULL) || (ifnames == NULL)) + return (NULL); + + iflist = malloc(sizeof (smb_hostifs_t)); + if (iflist == NULL) + return (NULL); + + bzero(iflist, sizeof (smb_hostifs_t)); + + (void) strlcpy(iflist->if_host, host, sizeof (iflist->if_host)); + (void) strlcpy(iflist->if_cmnt, (cmnt) ? cmnt : "", + sizeof (iflist->if_cmnt)); + + if ((ifname = strtok_r(ifnames, ",", &lasts)) == NULL) + return (NULL); + + iflist->if_names[if_num++] = strdup(ifname); + + while ((ifname = strtok_r(NULL, ",", &lasts)) != NULL) + iflist->if_names[if_num++] = strdup(ifname); + + iflist->if_num = if_num; + + for (if_num = 0; if_num < iflist->if_num; if_num++) { + if (iflist->if_names[if_num] == NULL) { + smb_nic_iflist_destroy(iflist); + return (NULL); + } + } + + return (iflist); +} + +/* + * smb_nic_iflist_destroy + * + * Frees allocated memory for the given IF names lists. + */ +static void +smb_nic_iflist_destroy(smb_hostifs_t *iflist) +{ + int i; + + if (iflist == NULL) + return; + + for (i = 0; i < iflist->if_num; i++) + free(iflist->if_names[i]); + + free(iflist); +} + +/* + * Functions to manage host/interface database + * + * Each entry in the hosts table associates a hostname with a + * list of interface names. The host/interface association could + * be added by calling smb_nic_addhost() and could be removed by + * calling smb_nic_delhost(). If the database exists and it contains + * valid information then the inteface list wouldn't be obtained + * from system using ioctl. + */ + +/* + * smb_nic_dbcreate + * + * Creates the host database based on the defined SQL statement. + * It also initializes db_info table. + */ +static int +smb_nic_dbcreate(void) +{ + sqlite *db = NULL; + char *errmsg = NULL; + int rc; + + (void) unlink(SMB_NIC_DB_NAME); + + db = sqlite_open(SMB_NIC_DB_NAME, 0600, &errmsg); + if (db == NULL) { + syslog(LOG_DEBUG, "failed to create host database (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SQLITE_CANTOPEN); + } + + sqlite_busy_timeout(db, SMB_NIC_DB_TIMEOUT); + rc = sqlite_exec(db, "BEGIN TRANSACTION", NULL, NULL, &errmsg); + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to begin database transaction (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + sqlite_close(db); + return (rc); + } + + if (sqlite_exec(db, SMB_NIC_DB_SQL, NULL, NULL, &errmsg) == SQLITE_OK) { + rc = sqlite_exec(db, "COMMIT TRANSACTION", NULL, NULL, + &errmsg); + if (rc == SQLITE_OK) + rc = smb_nic_dbsetinfo(db); + if (rc != SQLITE_OK) + rc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, + &errmsg); + } else { + syslog(LOG_ERR, "failed to initialize host database (%s)", + errmsg); + sqlite_freemem(errmsg); + rc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, + &errmsg); + } + + if (rc != SQLITE_OK) { + /* this is bad - database may be left in a locked state */ + syslog(LOG_DEBUG, "failed to close a transaction (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + } + + (void) sqlite_close(db); + return (rc); +} + +/* + * smb_nic_dbopen + * + * Opens host database with the given mode. + */ +static sqlite * +smb_nic_dbopen(int mode) +{ + sqlite *db; + char *errmsg = NULL; + + db = sqlite_open(SMB_NIC_DB_NAME, mode, &errmsg); + if (db == NULL) { + syslog(LOG_ERR, "failed to open group database (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + } + + return (db); +} + +/* + * smb_nic_dbclose + * + * Closes the given database handle + */ +static void +smb_nic_dbclose(sqlite *db) +{ + if (db) { + sqlite_close(db); + } +} + +static boolean_t +smb_nic_dbexists(void) +{ + return (access(SMB_NIC_DB_NAME, F_OK) == 0); +} + +static boolean_t +smb_nic_dbvalidate(void) +{ + sqlite *db; + char *errmsg = NULL; + char *sql; + char **result; + int nrow, ncol; + boolean_t check = B_TRUE; + int rc; + + sql = sqlite_mprintf("SELECT * FROM db_info"); + if (sql == NULL) + return (B_FALSE); + + db = smb_nic_dbopen(SMB_NIC_DB_ORW); + if (db == NULL) { + sqlite_freemem(sql); + return (B_FALSE); + } + + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "smb_nic_dbvalidate: failed to get db_info" + " (%s)", NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + smb_nic_dbclose(db); + return (B_FALSE); + } + + if (nrow != 1 || ncol != 3) { + syslog(LOG_DEBUG, "smb_nic_dbvalidate: bad db_info table"); + sqlite_free_table(result); + smb_nic_dbclose(db); + return (B_FALSE); + } + + if ((atoi(result[3]) != SMB_NIC_DB_VERMAJOR) || + (atoi(result[4]) != SMB_NIC_DB_VERMINOR) || + (atoi(result[5]) != SMB_NIC_DB_MAGIC)) { + syslog(LOG_DEBUG, "smb_nic_dbvalidate: bad db_info content"); + sqlite_free_table(result); + smb_nic_dbclose(db); + return (B_FALSE); + } + sqlite_free_table(result); + + sql = sqlite_mprintf("SELECT hostname FROM hosts"); + if (sql == NULL) { + smb_nic_dbclose(db); + return (B_FALSE); + } + + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "smb_nic_dbvalidate: failed to count (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + smb_nic_dbclose(db); + return (B_FALSE); + } + + sqlite_free_table(result); + + if (nrow == 0) + /* No hosts in the database */ + check = B_FALSE; + + smb_nic_dbclose(db); + return (check); +} + +static int +smb_nic_dbaddhost(const char *host, const char *cmnt, char *if_list) +{ + sqlite *db; + char *sql; + char *errmsg; + int rc; + + sql = sqlite_mprintf("REPLACE INTO hosts (hostname, comment, ifnames)" + "VALUES ('%s', '%q', '%s')", host, (cmnt) ? cmnt : "", if_list); + if (sql == NULL) + return (SQLITE_NOMEM); + + db = smb_nic_dbopen(SMB_NIC_DB_ORW); + if (db == NULL) { + sqlite_freemem(sql); + return (SQLITE_CANTOPEN); + } + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + smb_nic_dbclose(db); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "smb_nic_dbaddhost: failed to insert %s (%s)", + host, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + } + + return (rc); +} + +static int +smb_nic_dbdelhost(const char *host) +{ + sqlite *db; + char *sql; + char *errmsg; + int rc; + + sql = sqlite_mprintf("DELETE FROM hosts WHERE hostname = '%s'", host); + if (sql == NULL) + return (SQLITE_NOMEM); + + db = smb_nic_dbopen(SMB_NIC_DB_ORW); + if (db == NULL) { + sqlite_freemem(sql); + return (SQLITE_CANTOPEN); + } + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + smb_nic_dbclose(db); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "smb_nic_dbdelhost: failed to delete %s (%s)", + host, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + } + + return (rc); +} + +/* + * smb_nic_dbsetinfo + * + * Initializes the db_info table upon database creation. + */ +static int +smb_nic_dbsetinfo(sqlite *db) +{ + char *errmsg = NULL; + char *sql; + int rc; + + sql = sqlite_mprintf("INSERT INTO db_info (ver_major, ver_minor," + " magic) VALUES (%d, %d, %d)", SMB_NIC_DB_VERMAJOR, + SMB_NIC_DB_VERMINOR, SMB_NIC_DB_MAGIC); + + if (sql == NULL) + return (SQLITE_NOMEM); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "smb_nic_dbsetinfo: failed to insert database" + " information (%s)", NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + } + + return (rc); +} diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c b/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c index cc0cddebcd..1c9ff0707e 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c @@ -36,12 +36,17 @@ #include <fcntl.h> #include <thread.h> #include <pwd.h> +#include <dlfcn.h> +#include <link.h> #include <smbsrv/libsmb.h> #define SMB_PASSWD "/var/smb/smbpasswd" #define SMB_OPASSWD "/var/smb/osmbpasswd" #define SMB_PASSTEMP "/var/smb/ptmp" #define SMB_PASSLCK "/var/smb/.pwd.lock" +#define SMB_LIBPALT "/usr/lib/smbsrv" +#define SMB_LIBNALT "libsmb_pwd.so" +#define SMB_LIB_ALT SMB_LIBPALT "/" SMB_LIBNALT #define SMB_PWD_DISABLE "*DIS*" #define SMB_PWD_BUFSIZE 256 @@ -69,12 +74,20 @@ static pid_t lck_pid = 0; /* process's pid at last lock */ static thread_t lck_tid = 0; /* thread that holds the lock */ static int fildes = -1; static mutex_t lck_lock = DEFAULTMUTEX; +static void *smb_pwd_hdl = NULL; typedef struct smb_pwbuf { char *pw_name; smb_passwd_t *pw_pwd; } smb_pwbuf_t; +static struct { + smb_passwd_t *(*smb_pwd_getpasswd)(const char *name, + smb_passwd_t *smbpw); + int (*smb_pwd_setcntl)(const char *name, int control); + int (*smb_pwd_setpasswd)(const char *name, const char *password); +} smb_pwd_ops; + static int smb_pwd_lock(void); static int smb_pwd_unlock(void); static int smb_pwd_flck(void); @@ -85,6 +98,45 @@ static int smb_pwd_fputent(FILE *, smb_pwbuf_t *); static int smb_pwd_chgpwent(smb_passwd_t *, const char *, int); static int smb_pwd_update(const char *, const char *, int); +void +smb_pwd_init(void) +{ + smb_pwd_hdl = dlopen(SMB_LIB_ALT, RTLD_NOW | RTLD_LOCAL); + + if (smb_pwd_hdl == NULL) + return; /* interposition library not found */ + + bzero((void *)&smb_pwd_ops, sizeof (smb_pwd_ops)); + + smb_pwd_ops.smb_pwd_getpasswd = + (smb_passwd_t *(*)())dlsym(smb_pwd_hdl, "smb_pwd_getpasswd"); + + smb_pwd_ops.smb_pwd_setcntl = + (int (*)())dlsym(smb_pwd_hdl, "smb_pwd_setcntl"); + + smb_pwd_ops.smb_pwd_setpasswd = + (int (*)())dlsym(smb_pwd_hdl, "smb_pwd_setpasswd"); + + if (smb_pwd_ops.smb_pwd_getpasswd == NULL || + smb_pwd_ops.smb_pwd_setcntl == NULL || + smb_pwd_ops.smb_pwd_setpasswd == NULL) { + (void) dlclose(smb_pwd_hdl); + smb_pwd_hdl = NULL; + + /* If error or function(s) are missing, use original lib */ + bzero((void *)&smb_pwd_ops, sizeof (smb_pwd_ops)); + } +} + +void +smb_pwd_fini(void) +{ + if (smb_pwd_hdl) { + (void) dlclose(smb_pwd_hdl); + smb_pwd_hdl = NULL; + } +} + /* * smb_pwd_get * @@ -102,6 +154,9 @@ smb_pwd_getpasswd(const char *name, smb_passwd_t *smbpw) int err; FILE *fp; + if (smb_pwd_ops.smb_pwd_getpasswd != NULL) + return (smb_pwd_ops.smb_pwd_getpasswd(name, smbpw)); + err = smb_pwd_lock(); if (err != SMB_PWE_SUCCESS) return (NULL); @@ -141,6 +196,9 @@ smb_pwd_getpasswd(const char *name, smb_passwd_t *smbpw) int smb_pwd_setpasswd(const char *name, const char *password) { + if (smb_pwd_ops.smb_pwd_setpasswd != NULL) + return (smb_pwd_ops.smb_pwd_setpasswd(name, password)); + return (smb_pwd_update(name, password, 0)); } @@ -153,6 +211,9 @@ smb_pwd_setpasswd(const char *name, const char *password) int smb_pwd_setcntl(const char *name, int control) { + if (smb_pwd_ops.smb_pwd_setcntl != NULL) + return (smb_pwd_ops.smb_pwd_setcntl(name, control)); + if (control == 0) return (SMB_PWE_SUCCESS); diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c b/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c index 4460e70154..7bc94ea1de 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c @@ -70,16 +70,17 @@ smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup) int ret = SMBD_SMF_OK; int err; - if (handle == NULL) { + if (handle == NULL) return (SMBD_SMF_SYSTEM_ERR); - } /* * only create a handle if it doesn't exist. It is ok to exist * since the pg handle will be set as a side effect. */ if (handle->scf_pg == NULL) - handle->scf_pg = scf_pg_create(handle->scf_handle); + if ((handle->scf_pg = + scf_pg_create(handle->scf_handle)) == NULL) + return (SMBD_SMF_SYSTEM_ERR); /* * if the pgroup exists, we are done. If it doesn't, then we @@ -584,6 +585,10 @@ smb_smf_scf_init(char *svc_name) if (scf_handle_bind(handle->scf_handle) == 0) { handle->scf_scope = scf_scope_create(handle->scf_handle); + + if (handle->scf_scope == NULL) + goto err; + if (scf_handle_get_local_scope( handle->scf_handle, handle->scf_scope) != 0) goto err; @@ -591,6 +596,9 @@ smb_smf_scf_init(char *svc_name) handle->scf_service = scf_service_create(handle->scf_handle); + if (handle->scf_service == NULL) + goto err; + if (scf_scope_get_service(handle->scf_scope, svc_name, handle->scf_service) != SCF_SUCCESS) { @@ -598,6 +606,10 @@ smb_smf_scf_init(char *svc_name) } handle->scf_pg = scf_pg_create(handle->scf_handle); + + if (handle->scf_pg == NULL) + goto err; + handle->scf_state = SCH_STATE_INIT; } else { goto err; diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_sqlite.h b/usr/src/lib/smbsrv/libsmb/common/smb_sqlite.h new file mode 100644 index 0000000000..336a478d54 --- /dev/null +++ b/usr/src/lib/smbsrv/libsmb/common/smb_sqlite.h @@ -0,0 +1,132 @@ +/* + * 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 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SMB_SQLITE_H +#define _SMB_SQLITE_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sqlite/sqlite.h> + +#ifdef _LP64 +/* + * We cannot make 64-bit version of libsqlite because the code + * has some problems. + */ + +/*ARGSUSED*/ +sqlite * +sqlite_open(const char *filename, int mode, char **errmsg) +{ + return (NULL); +} + +/*ARGSUSED*/ +void +sqlite_close(sqlite *db) +{ +} + +/*ARGSUSED*/ +char * +sqlite_mprintf(const char *fmt, ...) +{ + return (NULL); +} + +/*ARGSUSED*/ +void +sqlite_freemem(void *p) +{ +} + +/*ARGSUSED*/ +int +sqlite_compile(sqlite *db, const char *zSql, const char **pzTail, + sqlite_vm **ppVm, char **pzErrmsg) +{ + return (SQLITE_ERROR); +} + +/*ARGSUSED*/ +void +sqlite_free_table(char **res) +{ +} + +/*ARGSUSED*/ +int +sqlite_last_insert_rowid(sqlite *db) +{ + return (-1); +} + +/*ARGSUSED*/ +void +sqlite_busy_timeout(sqlite *db, int ms) +{ +} + +/*ARGSUSED*/ +int +sqlite_get_table(sqlite *db, const char *zSql, char ***pazResult, int *pnRow, + int *pnColumn, char **pzErrMsg) +{ + return (SQLITE_ERROR); +} + +/*ARGSUSED*/ +int +sqlite_step(sqlite_vm *pVm, int *pN, const char ***pazValue, + const char ***pazColName) +{ + return (SQLITE_ERROR); +} + +/*ARGSUSED*/ +int +sqlite_exec(sqlite *db, const char *zSql, sqlite_callback xCallback, void *pArg, + char **pzErrMsg) +{ + return (SQLITE_ERROR); +} + +/*ARGSUSED*/ +int +sqlite_finalize(sqlite_vm *pVm, char **pzErrMsg) +{ + return (SQLITE_ERROR); +} +#endif /* _LP64 */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SMB_SQLITE_H */ diff --git a/usr/src/lib/smbsrv/libsmbns/Makefile.com b/usr/src/lib/smbsrv/libsmbns/Makefile.com index f4a45a3cac..16eaaeeec0 100644 --- a/usr/src/lib/smbsrv/libsmbns/Makefile.com +++ b/usr/src/lib/smbsrv/libsmbns/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -41,8 +41,7 @@ OBJS_COMMON= \ smbns_netbios_cache.o \ smbns_netbios_datagram.o\ smbns_netbios_name.o \ - smbns_netlogon.o \ - smbns_nicconfig.o + smbns_netlogon.o OBJECTS= $(OBJS_COMMON) $(OBJS_SHARED) diff --git a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h index c9e6d62dae..d219598e2a 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h +++ b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h @@ -29,8 +29,6 @@ #pragma ident "%Z%%M% %I% %E% SMI" #include <ldap.h> -#include <net/if.h> - #include <smbsrv/libsmb.h> #ifdef __cplusplus @@ -105,35 +103,10 @@ extern int smb_netbios_start(void); extern void smb_netbios_shutdown(void); extern void smb_netbios_name_reconfig(void); -/* Browser Configure */ -extern void smb_browser_config(void); - -extern void smb_netlogon_request(int, int, char *); +/* Browser Functions */ +extern void smb_browser_reconfig(void); +extern void smb_browser_netlogon(char *); -/* - * NIC listing and config - */ -#define SIZE_IP 17 - -typedef struct { - char ifname[LIFNAMSIZ]; - uint32_t ip; - uint32_t mask; - uint32_t broadcast; - uint64_t flags; - boolean_t exclude; -} net_cfg_t; - -#define GATEWAY_FILE "/etc/defaultrouter" - -/* NIC Config functions */ -extern int smb_get_nameservers(struct in_addr *, int); -extern void smb_nic_build_info(void); -extern net_cfg_t *smb_nic_get_byind(int, net_cfg_t *); -extern net_cfg_t *smb_nic_get_bysubnet(uint32_t, net_cfg_t *); -extern net_cfg_t *smb_nic_get_byip(uint32_t, net_cfg_t *); -extern int smb_nic_get_num(void); -extern boolean_t smb_nic_status(char *, uint64_t); #ifdef __cplusplus } diff --git a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers index 32e2423de6..3607ef138d 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers @@ -43,19 +43,12 @@ SUNWprivate { dyndns_clear_rev_zone; dyndns_update; msdcs_lookup_ads; - smb_browser_config; - smb_get_nameservers; + smb_browser_netlogon; + smb_browser_reconfig; smb_kinit; smb_netbios_name_reconfig; smb_netbios_start; smb_netbios_shutdown; - smb_netlogon_request; - smb_nic_build_info; - smb_nic_get_byind; - smb_nic_get_byip; - smb_nic_get_bysubnet; - smb_nic_get_num; - smb_nic_status; local: *; }; diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c index 7ab634fd4d..8a1da0cc4e 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c @@ -48,62 +48,39 @@ #define SMB_SERVER_SIGNATURE 0xaa550415 -/* - * Macro definitions: - */ -static char *lanman = MAILSLOT_LANMAN; -static char *browse = MAILSLOT_BROWSE; - -typedef struct server_info { - uint32_t type; - uint32_t signature; - char major; - char minor; - char hostname[NETBIOS_NAME_SZ]; - char comment[SMB_PI_MAX_COMMENT]; - char update_count; - struct name_entry name; -} server_info_t; - -#define BROWSER_NF_INVALID 0x00 -#define BROWSER_NF_VALID 0x01 - -typedef struct browser_netinfo { - uint32_t flags; - int next_announce; - int reps; - int interval; - server_info_t server; - mutex_t mtx; -} browser_netinfo_t; - -/* - * Local Data Definitions: - */ -static struct browser_netinfo smb_browser_info[SMB_PI_MAX_NETWORKS]; - -static void smb_browser_init(void); - -static inline browser_netinfo_t * -smb_browser_getnet(int net) -{ - browser_netinfo_t *subnet; - - if (net < smb_nic_get_num()) { - subnet = &smb_browser_info[net]; - (void) mutex_lock(&subnet->mtx); - if (subnet->flags & BROWSER_NF_VALID) - return (subnet); - } - - return (0); -} +typedef struct smb_hostinfo { + list_node_t hi_lnd; + smb_nic_t hi_nic; + char hi_nbname[NETBIOS_NAME_SZ]; + name_entry_t hi_netname; + uint32_t hi_nextannouce; + int hi_reps; + int hi_interval; + uint8_t hi_updatecnt; + uint32_t hi_type; +} smb_hostinfo_t; + +typedef struct smb_browserinfo { + list_t bi_hlist; + int bi_hcnt; + rwlock_t bi_hlist_rwl; + boolean_t bi_changed; + mutex_t bi_mtx; +} smb_browserinfo_t; + +static smb_browserinfo_t smb_binfo; + +static int smb_browser_init(void); +static void smb_browser_infoinit(void); +static void smb_browser_infoterm(void); +static void smb_browser_infofree(void); -static inline void -smb_browser_putnet(browser_netinfo_t *netinfo) +void +smb_browser_reconfig(void) { - if (netinfo) - (void) mutex_unlock(&netinfo->mtx); + (void) mutex_lock(&smb_binfo.bi_mtx); + smb_binfo.bi_changed = B_TRUE; + (void) mutex_unlock(&smb_binfo.bi_mtx); } /* @@ -611,7 +588,7 @@ smb_browser_putnet(browser_netinfo_t *netinfo) int smb_browser_load_transact_header(unsigned char *buffer, int maxcnt, - int data_count, int reply, char *mailbox) + int data_count, int reply, char *mailbox) { smb_msgbuf_t mb; int mailboxlen; @@ -661,66 +638,21 @@ smb_browser_load_transact_header(unsigned char *buffer, int maxcnt, return (result); } -/* - * smb_net_id - * - * Lookup for the given IP in the NICs info table. - * If it finds a matching entry it'll return the index, - * otherwise returns -1. - * - * SMB network table and SMB browser info table share - * the same index. - */ -int -smb_net_id(uint32_t ipaddr) -{ - uint32_t myaddr, mask; - int net, smb_nc_cnt; - - smb_nc_cnt = smb_nic_get_num(); - for (net = 0; net < smb_nc_cnt; net++) { - net_cfg_t cfg; - if (smb_nic_get_byind(net, &cfg) == NULL) - break; - mask = cfg.mask; - myaddr = cfg.ip; - if ((ipaddr & mask) == (myaddr & mask)) - return (net); - } - - return (-1); -} - -/* - * smb_browser_get_srvname - * - */ -struct name_entry * -smb_browser_get_srvname(unsigned short netid) -{ - if (netid < smb_nic_get_num()) - return (&(smb_browser_info[netid].server.name)); - - return (NULL); -} - static int -smb_browser_addr_of_subnet(struct name_entry *name, int subnet, +smb_browser_addr_of_subnet(struct name_entry *name, smb_hostinfo_t *hinfo, struct name_entry *result) { uint32_t ipaddr, mask, saddr; struct addr_entry *addr; - int smb_nc_cnt; - net_cfg_t cfg; - smb_nc_cnt = smb_nic_get_num(); - if ((name == 0) || subnet >= smb_nc_cnt) + if (name == NULL) return (-1); - if (smb_nic_get_byind(subnet, &cfg) == NULL) + if (hinfo->hi_nic.nic_smbflags & SMB_NICF_ALIAS) return (-1); - ipaddr = cfg.ip; - mask = cfg.mask; + + ipaddr = hinfo->hi_nic.nic_ip; + mask = hinfo->hi_nic.nic_mask; *result = *name; addr = &name->addr_list; @@ -741,27 +673,15 @@ smb_browser_addr_of_subnet(struct name_entry *name, int subnet, static int -smb_browser_bcast_addr_of_subnet(struct name_entry *name, int net, +smb_browser_bcast_addr_of_subnet(struct name_entry *name, uint32_t bcast, struct name_entry *result) { - uint32_t broadcast; - int smb_nc_cnt; - net_cfg_t cfg; - - smb_nc_cnt = smb_nic_get_num(); - if (net >= smb_nc_cnt) - return (-1); - - if (name != 0 && name != result) + if (name != NULL && name != result) *result = *name; - if (smb_nic_get_byind(net, &cfg) == NULL) - return (-1); - - broadcast = cfg.broadcast; result->addr_list.sin.sin_family = AF_INET; result->addr_list.sinlen = sizeof (result->addr_list.sin); - result->addr_list.sin.sin_addr.s_addr = broadcast; + result->addr_list.sin.sin_addr.s_addr = bcast; result->addr_list.sin.sin_port = htons(DGM_SRVC_UDP_PORT); result->addr_list.forw = result->addr_list.back = &result->addr_list; return (0); @@ -839,16 +759,14 @@ smb_browser_bcast_addr_of_subnet(struct name_entry *name, int net, * HostAnnouncement frames on this name as described above for D(1d). */ -void -smb_browser_send_HostAnnouncement(int net, int32_t next_announcement, +static void +smb_browser_send_HostAnnouncement(smb_hostinfo_t *hinfo, + uint32_t next_announcement, boolean_t remove, struct addr_entry *addr, char suffix) { smb_msgbuf_t mb; int offset, announce_len, data_length; struct name_entry dest_name; - struct name_entry server_name; - struct browser_netinfo *subnet; - server_info_t *server; unsigned char *buffer; uint32_t type; char resource_domain[SMB_PI_MAX_DOMAIN]; @@ -857,16 +775,15 @@ smb_browser_send_HostAnnouncement(int net, int32_t next_announcement, return; (void) utf8_strupr(resource_domain); - if (addr == 0) { + if (addr == NULL) { /* Local master Browser */ - smb_init_name_struct( - (unsigned char *)resource_domain, suffix, + smb_init_name_struct((unsigned char *)resource_domain, suffix, 0, 0, 0, 0, 0, &dest_name); - if (smb_browser_bcast_addr_of_subnet(0, net, &dest_name) < 0) + if (smb_browser_bcast_addr_of_subnet(0, hinfo->hi_nic.nic_bcast, + &dest_name) < 0) return; } else { - smb_init_name_struct( - (unsigned char *)resource_domain, suffix, + smb_init_name_struct((unsigned char *)resource_domain, suffix, 0, 0, 0, 0, 0, &dest_name); dest_name.addr_list = *addr; dest_name.addr_list.forw = dest_name.addr_list.back = @@ -880,22 +797,14 @@ smb_browser_send_HostAnnouncement(int net, int32_t next_announcement, return; } - subnet = smb_browser_getnet(net); - if (subnet == 0) { - free(buffer); - return; - } - - server = &subnet->server; - data_length = 1 + 1 + 4 + 16 + 1 + 1 + 4 + 4 + - strlen(server->comment) + 1; + strlen(hinfo->hi_nic.nic_cmnt) + 1; - if ((offset = smb_browser_load_transact_header(buffer, + offset = smb_browser_load_transact_header(buffer, MAX_DATAGRAM_LENGTH, data_length, ONE_WAY_TRANSACTION, - browse)) < 0) { + MAILSLOT_BROWSE); - smb_browser_putnet(subnet); + if (offset < 0) { free(buffer); return; } @@ -905,60 +814,66 @@ smb_browser_send_HostAnnouncement(int net, int32_t next_announcement, * specifying a type of 0 just prior to shutting down, to allow it to * quickly be removed from the list of available servers. */ - type = (nb_status.state & NETBIOS_SHUTTING_DOWN) ? 0 : server->type; + if (remove || (nb_status.state & NETBIOS_SHUTTING_DOWN)) + type = 0; + else + type = hinfo->hi_type; smb_msgbuf_init(&mb, buffer + offset, MAX_DATAGRAM_LENGTH - offset, 0); + announce_len = smb_msgbuf_encode(&mb, "bbl16cbblls", - (char)HOST_ANNOUNCEMENT, /* Announcement opcode */ - (char)++subnet->server.update_count, + HOST_ANNOUNCEMENT, + ++hinfo->hi_updatecnt, next_announcement * 60000, /* Periodicity in MilliSeconds */ - server->hostname, /* Server name */ - server->major, /* our major version */ - server->minor, /* our minor version */ - type, /* server type */ - server->signature, /* Signature */ - server->comment); /* Let 'em know */ - - server_name = server->name; - smb_browser_putnet(subnet); + hinfo->hi_nbname, + SMB_VERSION_MAJOR, + SMB_VERSION_MINOR, + type, + SMB_SERVER_SIGNATURE, + hinfo->hi_nic.nic_cmnt); if (announce_len > 0) - (void) smb_netbios_datagram_send(&server_name, &dest_name, + (void) smb_netbios_datagram_send(&hinfo->hi_netname, &dest_name, buffer, offset + announce_len); free(buffer); smb_msgbuf_term(&mb); } -void +static void smb_browser_process_AnnouncementRequest(struct datagram *datagram, char *mailbox) { - struct browser_netinfo *subnet; - unsigned int next_announcement; + smb_hostinfo_t *hinfo; + uint32_t next_announcement; uint32_t delay = random() % 29; /* in seconds */ - int net; + boolean_t h_found = B_FALSE; - if (strcmp(mailbox, lanman) != 0) { + if (strcmp(mailbox, MAILSLOT_LANMAN) != 0) { syslog(LOG_DEBUG, "smb_browse: Wrong Mailbox (%s)", mailbox); return; } - net = smb_net_id(datagram->src.addr_list.sin.sin_addr.s_addr); - if (net < 0) { - /* We don't know who this is so ignore it... */ - return; - } - (void) sleep(delay); - subnet = smb_browser_getnet(net); - if (subnet) { - next_announcement = subnet->next_announce * 60 * 1000; - smb_browser_putnet(subnet); - smb_browser_send_HostAnnouncement(net, next_announcement, - &datagram->src.addr_list, 0x1D); + (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); + hinfo = list_head(&smb_binfo.bi_hlist); + while (hinfo) { + if ((hinfo->hi_nic.nic_ip & hinfo->hi_nic.nic_mask) == + (datagram->src.addr_list.sin.sin_addr.s_addr & + hinfo->hi_nic.nic_mask)) { + h_found = B_TRUE; + break; + } + hinfo = list_next(&smb_binfo.bi_hlist, hinfo); + } + + if (h_found) { + next_announcement = hinfo->hi_nextannouce * 60 * 1000; + smb_browser_send_HostAnnouncement(hinfo, next_announcement, + B_FALSE, &datagram->src.addr_list, 0x1D); } + (void) rw_unlock(&smb_binfo.bi_hlist_rwl); } void * @@ -1119,19 +1034,20 @@ smb_browser_dispatch(void *arg) * This name is registered by Primary Domain Controllers. */ -void +static void smb_browser_config(void) { + smb_hostinfo_t *hinfo; struct name_entry name; struct name_entry master; struct name_entry dest; struct name_entry *entry; - int smb_nc_cnt; - net_cfg_t cfg; - int net; char resource_domain[SMB_PI_MAX_DOMAIN]; + int rc; + + if (smb_browser_init() != 0) + return; - smb_browser_init(); if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0) return; (void) utf8_strupr(resource_domain); @@ -1142,18 +1058,17 @@ smb_browser_config(void) entry = smb_name_find_name(&name); smb_name_unlock_name(entry); - smb_nc_cnt = smb_nic_get_num(); - for (net = 0; net < smb_nc_cnt; net++) { - if (smb_nic_get_byind(net, &cfg) == NULL) - break; - if (cfg.exclude) - continue; - smb_init_name_struct( - (unsigned char *)resource_domain, 0x00, 0, - cfg.ip, htons(DGM_SRVC_UDP_PORT), + (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); + hinfo = list_head(&smb_binfo.bi_hlist); + while (hinfo) { + smb_init_name_struct((unsigned char *)resource_domain, 0x00, 0, + hinfo->hi_nic.nic_ip, htons(DGM_SRVC_UDP_PORT), NAME_ATTR_GROUP, NAME_ATTR_LOCAL, &name); (void) smb_name_add_name(&name); + + hinfo = list_next(&smb_binfo.bi_hlist, hinfo); } + (void) rw_unlock(&smb_binfo.bi_hlist_rwl); /* All our local master browsers */ smb_init_name_struct((unsigned char *)resource_domain, 0x1D, @@ -1161,16 +1076,23 @@ smb_browser_config(void) entry = smb_name_find_name(&dest); if (entry) { - for (net = 0; net < smb_nc_cnt; net++) { - if (smb_browser_addr_of_subnet(entry, net, &master) - == 0) { + (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); + hinfo = list_head(&smb_binfo.bi_hlist); + while (hinfo) { + rc = smb_browser_addr_of_subnet(entry, hinfo, &master); + if (rc == 0) { syslog(LOG_DEBUG, "smbd: Master browser found at %s", inet_ntoa(master.addr_list.sin.sin_addr)); } + hinfo = list_next(&smb_binfo.bi_hlist, hinfo); } + (void) rw_unlock(&smb_binfo.bi_hlist_rwl); + smb_name_unlock_name(entry); } + + /* Domain master browser */ smb_init_name_struct((unsigned char *)resource_domain, 0x1B, 0, 0, 0, 0, 0, &dest); @@ -1182,65 +1104,60 @@ smb_browser_config(void) } } -static void -smb_browser_init() +static int +smb_browser_init(void) { - struct browser_netinfo *subnet; - struct server_info *server; - char cmnt[SMB_PI_MAX_COMMENT], hostname[MAXHOSTNAMELEN]; - int i, j; - int smb_nc_cnt; - net_cfg_t cfg; - - (void) smb_gethostname(hostname, MAXHOSTNAMELEN, 1); - (void) smb_config_getstr(SMB_CI_SYS_CMNT, cmnt, sizeof (cmnt)); - - smb_nc_cnt = smb_nic_get_num(); - for (i = 0; i < smb_nc_cnt; i++) { - if (smb_nic_get_byind(i, &cfg) == NULL) - break; - if (cfg.exclude) - continue; + smb_hostinfo_t *hinfo; + smb_niciter_t ni; + uint32_t type; - subnet = &smb_browser_info[i]; - (void) mutex_lock(&subnet->mtx); + (void) rw_wrlock(&smb_binfo.bi_hlist_rwl); + smb_browser_infofree(); - /* One Minute announcements for first five */ - subnet->flags = BROWSER_NF_VALID; - subnet->next_announce = 1; - subnet->interval = 1; - subnet->reps = 5; - - server = &subnet->server; - bzero(server, sizeof (struct server_info)); - - server->type = MY_SERVER_TYPE; - server->major = SMB_VERSION_MAJOR; - server->minor = SMB_VERSION_MINOR; - server->signature = SMB_SERVER_SIGNATURE; - (void) strlcpy(server->comment, cmnt, SMB_PI_MAX_COMMENT); - - (void) snprintf(server->hostname, NETBIOS_NAME_SZ, "%.15s", - hostname); - - /* - * 00 is workstation service. - * 20 is file server service. - */ - smb_init_name_struct((unsigned char *)server->hostname, 0x20, 0, - cfg.ip, htons(DGM_SRVC_UDP_PORT), - NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &server->name); - - (void) mutex_unlock(&subnet->mtx); + if (smb_nic_getfirst(&ni) != 0) { + (void) rw_unlock(&smb_binfo.bi_hlist_rwl); + return (-1); } - /* Invalidate unconfigured NICs */ - for (j = i; j < SMB_PI_MAX_NETWORKS; j++) { - subnet = &smb_browser_info[j]; - (void) mutex_lock(&subnet->mtx); - subnet->flags = BROWSER_NF_INVALID; - (void) mutex_unlock(&subnet->mtx); - } + type = MY_SERVER_TYPE; + if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) + type |= SV_DOMAIN_MEMBER; + + do { + if (ni.ni_nic.nic_smbflags & SMB_NICF_NBEXCL) + continue; + + hinfo = malloc(sizeof (smb_hostinfo_t)); + if (hinfo == NULL) { + smb_browser_infofree(); + (void) rw_unlock(&smb_binfo.bi_hlist_rwl); + return (-1); + } + + hinfo->hi_nic = ni.ni_nic; + /* One Minute announcements for first five */ + hinfo->hi_nextannouce = 1; + hinfo->hi_interval = 1; + hinfo->hi_reps = 5; + hinfo->hi_updatecnt = 0; + hinfo->hi_type = type; + + /* This is the name used for HostAnnouncement */ + (void) strlcpy(hinfo->hi_nbname, hinfo->hi_nic.nic_host, + NETBIOS_NAME_SZ); + (void) utf8_strupr(hinfo->hi_nbname); + + /* 0x20: file server service */ + smb_init_name_struct((unsigned char *)hinfo->hi_nbname, + 0x20, 0, hinfo->hi_nic.nic_ip, htons(DGM_SRVC_UDP_PORT), + NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &hinfo->hi_netname); + + list_insert_tail(&smb_binfo.bi_hlist, hinfo); + smb_binfo.bi_hcnt++; + } while (smb_nic_getnext(&ni) == 0); + + (void) rw_unlock(&smb_binfo.bi_hlist_rwl); + return (0); } /* @@ -1251,24 +1168,16 @@ smb_browser_init() * is a member of domain "D", this frame is sent to the NETBIOS unique name * D(1d) and mailslot "\\MAILSLOT\\BROWSE". */ -void -smb_browser_non_master_duties(int net) +static void +smb_browser_non_master_duties(smb_hostinfo_t *hinfo, boolean_t remove) { - struct browser_netinfo *subnet; struct name_entry name; struct name_entry *dest; struct addr_entry addr; - int interval; char resource_domain[SMB_PI_MAX_DOMAIN]; - subnet = smb_browser_getnet(net); - if (subnet == 0) - return; - - interval = subnet->interval; - smb_browser_putnet(subnet); - - smb_browser_send_HostAnnouncement(net, interval, 0, 0x1D); + smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval, + remove, 0, 0x1D); if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0) return; @@ -1281,41 +1190,39 @@ smb_browser_non_master_duties(int net) addr = dest->addr_list; addr.forw = addr.back = &addr; smb_name_unlock_name(dest); - smb_browser_send_HostAnnouncement(net, interval, &addr, 0x1D); + smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval, + remove, &addr, 0x1D); } else { - smb_init_name_struct( - (unsigned char *)resource_domain, 0x1B, + smb_init_name_struct((unsigned char *)resource_domain, 0x1B, 0, 0, 0, 0, 0, &name); if ((dest = smb_name_find_name(&name))) { addr = dest->addr_list; addr.forw = addr.back = &addr; smb_name_unlock_name(dest); - smb_browser_send_HostAnnouncement(net, interval, - &addr, 0x1B); + smb_browser_send_HostAnnouncement(hinfo, + remove, hinfo->hi_interval, &addr, 0x1B); } } - subnet = smb_browser_getnet(net); /* * One Minute announcements for first five - * minutes, one munute longer each round + * minutes, one minute longer each round * until 12 minutes and every 12 minutes * thereafter. */ - if (--subnet->reps == 0) { - if (subnet->interval < 12) - subnet->interval++; + if (--hinfo->hi_reps == 0) { + if (hinfo->hi_interval < 12) + hinfo->hi_interval++; - subnet->reps = 1; + hinfo->hi_reps = 1; } - subnet->next_announce = subnet->interval; - smb_browser_putnet(subnet); + hinfo->hi_nextannouce = hinfo->hi_interval; } /* - * browser_sleep + * smb_browser_sleep * * Put browser in 1 minute sleep if netbios services are not * shutting down and both name and datagram services are still @@ -1324,10 +1231,10 @@ smb_browser_non_master_duties(int net) * 1 if everything is ok or 0 if browser shouldn't continue * running. */ -static int -browser_sleep() +static boolean_t +smb_browser_sleep(void) { - int slept = 0; + boolean_t slept = B_FALSE; timestruc_t to; (void) mutex_lock(&nb_status.mtx); @@ -1337,21 +1244,21 @@ browser_sleep() if (slept) { (void) mutex_unlock(&nb_status.mtx); - return (1); + return (B_TRUE); } to.tv_sec = 60; /* 1 minute */ to.tv_nsec = 0; (void) cond_reltimedwait(&nb_status.cv, &nb_status.mtx, &to); - slept = 1; + slept = B_TRUE; } (void) mutex_unlock(&nb_status.mtx); - return (0); + return (B_FALSE); } /* - * smb_browser_start + * smb_browser_daemon * * Smb Netbios browser daemon. */ @@ -1359,38 +1266,125 @@ browser_sleep() void * smb_browser_daemon(void *arg) { - int net; - int next_announce; - struct browser_netinfo *subnet; - int run = 1; - int smb_nc_cnt; - net_cfg_t cfg; + smb_hostinfo_t *hinfo; + smb_browser_infoinit(); smb_browser_config(); - nb_status.state |= NETBIOS_BROWSER_RUNNING; + smb_netbios_chg_status(NETBIOS_BROWSER_RUNNING, 1); - while (run) { - smb_nc_cnt = smb_nic_get_num(); - for (net = 0; net < smb_nc_cnt; net++) { - if (smb_nic_get_byind(net, &cfg) == NULL) - break; - if (cfg.exclude) +restart: + do { + (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); + hinfo = list_head(&smb_binfo.bi_hlist); + while (hinfo) { + if (--hinfo->hi_nextannouce > 0 || + hinfo->hi_nic.nic_bcast == 0) { + hinfo = list_next(&smb_binfo.bi_hlist, hinfo); continue; + } - subnet = smb_browser_getnet(net); - next_announce = --subnet->next_announce; - smb_browser_putnet(subnet); + smb_browser_non_master_duties(hinfo, B_FALSE); - if (next_announce > 0 || cfg.broadcast == 0) - continue; + /* Check to see whether reconfig is needed */ + (void) mutex_lock(&smb_binfo.bi_mtx); + if (smb_binfo.bi_changed) { + smb_binfo.bi_changed = B_FALSE; + (void) mutex_unlock(&smb_binfo.bi_mtx); + (void) rw_unlock(&smb_binfo.bi_hlist_rwl); + smb_browser_config(); + goto restart; + } + (void) mutex_unlock(&smb_binfo.bi_mtx); - smb_browser_non_master_duties(net); + hinfo = list_next(&smb_binfo.bi_hlist, hinfo); } + (void) rw_unlock(&smb_binfo.bi_hlist_rwl); + } while (smb_browser_sleep()); - run = browser_sleep(); - } - + smb_browser_infoterm(); smb_netbios_chg_status(NETBIOS_BROWSER_RUNNING, 0); return (0); } + +/* + * smb_browser_netlogon + * + * Sends SAMLOGON/NETLOGON request for all host/ips, except + * aliases, to find a domain controller. + */ +void +smb_browser_netlogon(char *domain) +{ + smb_hostinfo_t *hinfo; + int protocol; + + if (smb_config_getbool(SMB_CI_DOMAIN_MEMB)) + protocol = NETLOGON_PROTO_SAMLOGON; + else + protocol = NETLOGON_PROTO_NETLOGON; + + (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); + hinfo = list_head(&smb_binfo.bi_hlist); + while (hinfo) { + if ((hinfo->hi_nic.nic_smbflags & SMB_NICF_ALIAS) == 0) + smb_netlogon_request(&hinfo->hi_netname, protocol, + domain); + hinfo = list_next(&smb_binfo.bi_hlist, hinfo); + } + (void) rw_unlock(&smb_binfo.bi_hlist_rwl); +} + +/* + * smb_browser_infoinit + * + * This function is called only once when browser daemon starts + * to initialize global smb_binfo structure + */ +static void +smb_browser_infoinit(void) +{ + (void) rw_wrlock(&smb_binfo.bi_hlist_rwl); + list_create(&smb_binfo.bi_hlist, sizeof (smb_hostinfo_t), + offsetof(smb_hostinfo_t, hi_lnd)); + smb_binfo.bi_hcnt = 0; + (void) rw_unlock(&smb_binfo.bi_hlist_rwl); + + (void) mutex_lock(&smb_binfo.bi_mtx); + smb_binfo.bi_changed = B_FALSE; + (void) mutex_unlock(&smb_binfo.bi_mtx); +} + +/* + * smb_browser_infoterm + * + * This function is called only once when browser daemon stops + * to destruct smb_binfo structure + */ +static void +smb_browser_infoterm(void) +{ + (void) rw_wrlock(&smb_binfo.bi_hlist_rwl); + smb_browser_infofree(); + list_destroy(&smb_binfo.bi_hlist); + (void) rw_unlock(&smb_binfo.bi_hlist_rwl); +} + +/* + * smb_browser_infofree + * + * Removes all the hostinfo structures from the browser list + * and frees the allocated memory + */ +static void +smb_browser_infofree(void) +{ + smb_hostinfo_t *hinfo; + + while ((hinfo = list_head(&smb_binfo.bi_hlist)) != NULL) { + list_remove(&smb_binfo.bi_hlist, hinfo); + free(hinfo); + } + + smb_binfo.bi_hcnt = 0; +} diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c index 8d96268c0a..46d1c5e47e 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c @@ -1671,11 +1671,11 @@ dyndns_remove_entry(int update_zone, const char *hostname, const char *ip_addr, int dyndns_update(void) { - int i, forw_update_ok, error; + int forw_update_ok, error; char fqdn[MAXHOSTNAMELEN]; char *my_ip; - int nc_cnt; struct in_addr addr; + smb_niciter_t ni; int rc; if (!smb_config_getbool(SMB_CI_DYNDNS_ENABLE)) @@ -1684,8 +1684,6 @@ dyndns_update(void) if (smb_getfqhostname(fqdn, MAXHOSTNAMELEN) != 0) return (-1); - nc_cnt = smb_nic_get_num(); - error = 0; forw_update_ok = 0; @@ -1698,17 +1696,14 @@ dyndns_update(void) error++; } - for (i = 0; i < nc_cnt; i++) { - net_cfg_t cfg; - if (smb_nic_get_byind(i, &cfg) == NULL) - break; - addr.s_addr = cfg.ip; - if (addr.s_addr == 0) - continue; - if (smb_nic_status(cfg.ifname, IFF_STANDBY) || - smb_nic_status(cfg.ifname, IFF_PRIVATE)) + if (smb_nic_getfirst(&ni) != 0) + return (-1); + + do { + if (ni.ni_nic.nic_sysflags & (IFF_STANDBY | IFF_PRIVATE)) continue; + addr.s_addr = ni.ni_nic.nic_ip; my_ip = (char *)strdup(inet_ntoa(addr)); if (my_ip == NULL) { error++; @@ -1733,7 +1728,7 @@ dyndns_update(void) error++; (void) free(my_ip); - } + } while (smb_nic_getnext(&ni) == 0); return ((error == 0) ? 0 : -1); } @@ -1752,11 +1747,11 @@ dyndns_update(void) int dyndns_clear_rev_zone(void) { - int i, error; + int error; char fqdn[MAXHOSTNAMELEN]; char *my_ip; - int nc_cnt; struct in_addr addr; + smb_niciter_t ni; int rc; if (!smb_config_getbool(SMB_CI_DYNDNS_ENABLE)) @@ -1765,21 +1760,16 @@ dyndns_clear_rev_zone(void) if (smb_getfqhostname(fqdn, MAXHOSTNAMELEN) != 0) return (-1); - nc_cnt = smb_nic_get_num(); - error = 0; - for (i = 0; i < nc_cnt; i++) { - net_cfg_t cfg; - if (smb_nic_get_byind(i, &cfg) == NULL) - break; - addr.s_addr = cfg.ip; - if (addr.s_addr == 0) - continue; - if (smb_nic_status(cfg.ifname, IFF_STANDBY) || - smb_nic_status(cfg.ifname, IFF_PRIVATE)) + if (smb_nic_getfirst(&ni) != 0) + return (-1); + + do { + if (ni.ni_nic.nic_sysflags & (IFF_STANDBY | IFF_PRIVATE)) continue; + addr.s_addr = ni.ni_nic.nic_ip; my_ip = (char *)strdup(inet_ntoa(addr)); if (my_ip == NULL) { error++; @@ -1791,7 +1781,7 @@ dyndns_clear_rev_zone(void) error++; (void) free(my_ip); - } + } while (smb_nic_getnext(&ni) == 0); return ((error == 0) ? 0 : -1); } diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c index 4f8340dcca..0f9380c114 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c @@ -159,27 +159,26 @@ smb_netbios_start(void) static void * smb_netbios_timer(void *arg) { - static unsigned int ticks; + static unsigned int ticks = 0; smb_netbios_chg_status(NETBIOS_TIMER_RUNNING, 1); while ((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) { (void) sleep(1); + ticks++; - if (nb_status.state & NETBIOS_DATAGRAM_SVC_RUNNING) - smb_netbios_datagram_tick(); - else + if ((nb_status.state & NETBIOS_DATAGRAM_SVC_RUNNING) == 0) break; - if (nb_status.state & NETBIOS_NAME_SVC_RUNNING) { - smb_netbios_name_tick(); - - /* every 10 minutes */ - if ((ticks % 600) == 0) - smb_netbios_cache_clean(); - } - else + if ((nb_status.state & NETBIOS_NAME_SVC_RUNNING) == 0) break; + + smb_netbios_datagram_tick(); + smb_netbios_name_tick(); + + /* every 10 minutes */ + if ((ticks % 600) == 0) + smb_netbios_cache_clean(); } nb_status.state &= ~NETBIOS_TIMER_RUNNING; @@ -218,37 +217,16 @@ void smb_encode_netbios_name(unsigned char *name, char suffix, unsigned char *scope, struct name_entry *dest) { - char tmp_name[NETBIOS_NAME_SZ]; - mts_wchar_t wtmp_name[NETBIOS_NAME_SZ]; - unsigned int cpid; - int len; - size_t rc; - - len = 0; - rc = mts_mbstowcs(wtmp_name, (const char *)name, NETBIOS_NAME_SZ); - - if (rc != (size_t)-1) { - wtmp_name[NETBIOS_NAME_SZ - 1] = 0; - cpid = oem_get_smb_cpid(); - rc = unicodestooems(tmp_name, wtmp_name, NETBIOS_NAME_SZ, cpid); - if (rc > 0) - len = strlen(tmp_name); - } - - (void) memset(dest->name, ' ', NETBIOS_NAME_SZ - 1); - if (len) { - (void) utf8_strupr(tmp_name); - (void) memcpy(dest->name, tmp_name, len); - } - dest->name[NETBIOS_NAME_SZ - 1] = suffix; + smb_tonetbiosname((char *)name, (char *)dest->name, suffix); - if (scope == NULL) { - (void) smb_config_getstr(SMB_CI_NBSCOPE, (char *)dest->scope, - NETBIOS_DOMAIN_NAME_MAX); - } else { + if (scope) { (void) strlcpy((char *)dest->scope, (const char *)scope, - NETBIOS_DOMAIN_NAME_MAX); + sizeof (dest->scope)); + } else { + (void) smb_config_getstr(SMB_CI_NBSCOPE, (char *)dest->scope, + sizeof (dest->scope)); } + (void) utf8_strupr((char *)dest->scope); } diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.h b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.h index 54ac5cf2ab..6c91115fa3 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.h +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,928 +28,6 @@ #pragma ident "%Z%%M% %I% %E% SMI" -/* - * 4.2. NAME SERVICE PACKETS - * - * 4.2.1. GENERAL FORMAT OF NAME SERVICE PACKETS - * - * The NetBIOS Name Service packets follow the packet structure defined - * in the Domain Name Service (DNS) RFC 883 [7 (pg 26-31)]. The - * structures are compatible with the existing DNS packet formats, - * however, additional types and codes have been added to work with - * NetBIOS. - * - * If Name Service packets are sent over a TCP connection they are - * preceded by a 16 bit unsigned integer representing the length of the - * Name Service packet. - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * + ------ ------- + - * | HEADER | - * + ------ ------- + - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION ENTRIES / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / ANSWER RESOURCE RECORDS / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / AUTHORITY RESOURCE RECORDS / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / ADDITIONAL RESOURCE RECORDS / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -/* - * 4.2.1.1 HEADER - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID | OPCODE | NM_FLAGS | RCODE | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | QDCOUNT | ANCOUNT | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NSCOUNT | ARCOUNT | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Field Description - * - * NAME_TRN_ID Transaction ID for Name Service Transaction. - * Requester places a unique value for each active - * transaction. Responder puts NAME_TRN_ID value - * from request packet in response packet. - * - * OPCODE Packet type code, see table below. - * - * NM_FLAGS Flags for operation, see table below. - * - * RCODE Result codes of request. Table of RCODE values - * for each response packet below. - * - * QDCOUNT Unsigned 16 bit integer specifying the number of - * entries in the question section of a Name - * Service packet. Always zero (0) for responses. - * Must be non-zero for all NetBIOS Name requests. - * - * ANCOUNT Unsigned 16 bit integer specifying the number of - * resource records in the answer section of a Name - * Service packet. - * - * NSCOUNT Unsigned 16 bit integer specifying the number of - * resource records in the authority section of a - * Name Service packet. - * - * ARCOUNT Unsigned 16 bit integer specifying the number of - * resource records in the additional records - * section of a Name Service packet. - */ - - -/* - * The OPCODE field is defined as: - * - * 0 1 2 3 4 - * +---+---+---+---+---+ - * | R | OPCODE | - * +---+---+---+---+---+ - * - * Symbol Bit(s) Description - * - * OPCODE 1-4 Operation specifier: - * 0 = query - * 5 = registration - * 6 = release - * 7 = WACK - * 8 = refresh - * - * R 0 RESPONSE flag: - * if bit == 0 then request packet - * if bit == 1 then response packet. - */ - -/* - * The NM_FLAGS field is defined as: - * - * - * 0 1 2 3 4 5 6 - * +---+---+---+---+---+---+---+ - * |AA |TC |RD |RA | 0 | 0 | B | - * +---+---+---+---+---+---+---+ - * - * Symbol Bit(s) Description - * - * B 6 Broadcast Flag. - * = 1: packet was broadcast or multicast - * = 0: unicast - * - * RA 3 Recursion Available Flag. - * - * Only valid in responses from a NetBIOS Name - * Server -- must be zero in all other - * responses. - * - * If one (1) then the NBNS supports recursive - * query, registration, and release. - * - * If zero (0) then the end-node must iterate - * for query and challenge for registration. - * - * RD 2 Recursion Desired Flag. - * - * May only be set on a request to a NetBIOS - * Name Server. - * - * The NBNS will copy its state into the - * response packet. - * - * If one (1) the NBNS will iterate on the - * query, registration, or release. - * - * TC 1 Truncation Flag. - * - * Set if this message was truncated because the - * datagram carrying it would be greater than - * 576 bytes in length. Use TCP to get the - * information from the NetBIOS Name Server. - * - * AA 0 Authoritative Answer flag. - * - * Must be zero (0) if R flag of OPCODE is zero - * (0). - * - * If R flag is one (1) then if AA is one (1) - * then the node responding is an authority for - * the domain name. - * - * End nodes responding to queries always set - * this bit in responses. - */ - -/* - * 4.2.1.2 QUESTION SECTION - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | QUESTION_TYPE | QUESTION_CLASS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Field Description - * - * QUESTION_NAME The compressed name representation of the - * NetBIOS name for the request. - * - * QUESTION_TYPE The type of request. The values for this field - * are specified for each request. - * - * QUESTION_CLASS The class of the request. The values for this - * field are specified for each request. - * - * QUESTION_TYPE is defined as: - * - * Symbol Value Description: - * - * NB 0x0020 NetBIOS general Name Service Resource Record - * NBSTAT 0x0021 NetBIOS NODE STATUS Resource Record (See NODE - * STATUS REQUEST) - * - * QUESTION_CLASS is defined as: - * - * Symbol Value Description: - * - * IN 0x0001 Internet class - */ - -/* - * 4.2.1.3 RESOURCE RECORD - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | RR_TYPE | RR_CLASS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | RDLENGTH | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | - * / / - * / RDATA / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Field Description - * - * RR_NAME The compressed name representation of the - * NetBIOS name corresponding to this resource - * record. - * - * RR_TYPE Resource record type code - * - * RR_CLASS Resource record class code - * - * TTL The Time To Live of a the resource record's - * name. - * - * RDLENGTH Unsigned 16 bit integer that specifies the - * number of bytes in the RDATA field. - * - * RDATA RR_CLASS and RR_TYPE dependent field. Contains - * the resource information for the NetBIOS name. - * - * RESOURCE RECORD RR_TYPE field definitions: - * - * Symbol Value Description: - * - * A 0x0001 IP address Resource Record (See REDIRECT NAME - * QUERY RESPONSE) - * NS 0x0002 Name Server Resource Record (See REDIRECT - * NAME QUERY RESPONSE) - * NULL 0x000A NULL Resource Record (See WAIT FOR - * ACKNOWLEDGEMENT RESPONSE) - * NB 0x0020 NetBIOS general Name Service Resource Record - * (See NB_FLAGS and NB_ADDRESS, below) - * NBSTAT 0x0021 NetBIOS NODE STATUS Resource Record (See NODE - * STATUS RESPONSE) - * - * RESOURCE RECORD RR_CLASS field definitions: - * - * Symbol Value Description: - * - * IN 0x0001 Internet class - * - * NB_FLAGS field of the RESOURCE RECORD RDATA field for RR_TYPE of - * "NB": - * - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * | G | ONT | RESERVED | - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * - * Symbol Bit(s) Description: - * - * RESERVED 3-15 Reserved for future use. Must be zero (0). - * ONT 1,2 Owner Node Type: - * 00 = B node - * 01 = P node - * 10 = M node - * 11 = Reserved for future use - * For registration requests this is the - * claimant's type. - * For responses this is the actual owner's - * type. - * - * G 0 Group Name Flag. - * If one (1) then the RR_NAME is a GROUP - * NetBIOS name. - * If zero (0) then the RR_NAME is a UNIQUE - * NetBIOS name. - * - * The NB_ADDRESS field of the RESOURCE RECORD RDATA field for - * RR_TYPE of "NB" is the IP address of the name's owner. - */ - -/* - * 4.2.2. NAME REGISTRATION REQUEST - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |0| 0x5 |0|0|1|0|0 0|B| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0001 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Since the RR_NAME is the same name as the QUESTION_NAME, the - * RR_NAME representation must use pointers to the QUESTION_NAME - * name's labels to guarantee the length of the datagram is less - * than the maximum 576 bytes. See section above on name formats - * and also page 31 and 32 of RFC 883, Domain Names - Implementation - * and Specification, for a complete description of compressed name - * label pointers. - */ - -/* - * 4.2.3 NAME OVERWRITE REQUEST & DEMAND - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |0| 0x5 |0|0|0|0|0 0|B| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0001 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -/* - * 4.2.4 NAME REFRESH REQUEST - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |0| 0x9 |0|0|0|0|0 0|B| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0001 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -/* - * 4.2.5 POSITIVE NAME REGISTRATION RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x5 |1|0|1|1|0 0|0| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -/* - * 4.2.6 NEGATIVE NAME REGISTRATION RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x5 |1|0|1|1|0 0|0| RCODE | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * RCODE field values: - * - * Symbol Value Description: - * - * FMT_ERR 0x1 Format Error. Request was invalidly - * formatted. - * SRV_ERR 0x2 Server failure. Problem with NBNS, cannot - * process name. - * IMP_ERR 0x4 Unsupported request error. Allowable only - * for challenging NBNS when gets an Update type - * registration request. - * RFS_ERR 0x5 Refused error. For policy reasons server - * will not register this name from this host. - * ACT_ERR 0x6 Active error. Name is owned by another node. - * CFT_ERR 0x7 Name in conflict error. A UNIQUE name is - * owned by more than one node. - */ - -/* - * 4.2.7 END-NODE CHALLENGE REGISTRATION RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x5 |1|0|1|0|0 0|0| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -/* - * 4.2.8 NAME CONFLICT DEMAND - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x5 |1|0|1|1|0 0|0| 0x7 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x00000000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 |0|ONT|0| 0x000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x00000000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * This packet is identical to a NEGATIVE NAME REGISTRATION RESPONSE - * with RCODE = CFT_ERR. - */ - -/* - * 4.2.9 NAME RELEASE REQUEST & DEMAND - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |0| 0x6 |0|0|0|0|0 0|B| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0001 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x00000000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Since the RR_NAME is the same name as the QUESTION_NAME, the - * RR_NAME representation must use label string pointers to the - * QUESTION_NAME labels to guarantee the length of the datagram is - * less than the maximum 576 bytes. This is the same condition as - * with the NAME REGISTRATION REQUEST. - */ - -/* - * 4.2.10 POSITIVE NAME RELEASE RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x6 |1|0|0|0|0 0|0| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -/* - * 4.2.11 NEGATIVE NAME RELEASE RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x6 |1|0|0|0|0 0|0| RCODE | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * RCODE field values: - * - * Symbol Value Description: - * - * FMT_ERR 0x1 Format Error. Request was invalidly - * formatted. - * - * SRV_ERR 0x2 Server failure. Problem with NBNS, cannot - * process name. - * - * RFS_ERR 0x5 Refused error. For policy reasons server - * will not release this name from this host. - * - * ACT_ERR 0x6 Active error. Name is owned by another node. - * Only that node may release it. A NetBIOS - * Name Server can optionally allow a node to - * release a name it does not own. This would - * facilitate detection of inactive names for - * nodes that went down silently. - */ - -/* - * 4.2.12 NAME QUERY REQUEST - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |0| 0x0 |0|0|1|0|0 0|B| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0001 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -/* - * 4.2.13 POSITIVE NAME QUERY RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x0 |1|T|1|?|0 0|0| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | RDLENGTH | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | - * | | - * / ADDR_ENTRY ARRAY / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * The ADDR_ENTRY ARRAY a sequence of zero or more ADDR_ENTRY - * records. Each ADDR_ENTRY record represents an owner of a name. - * For group names there may be multiple entries. However, the list - * may be incomplete due to packet size limitations. Bit 22, "T", - * will be set to indicate truncated data. - * - * Each ADDR_ENTRY has the following format: - * - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_FLAGS | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS (continued) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -/* - * 4.2.14 NEGATIVE NAME QUERY RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x0 |1|0|1|?|0 0|0| RCODE | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NULL (0x000A) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x00000000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * RCODE field values: - * - * Symbol Value Description - * - * FMT_ERR 0x1 Format Error. Request was invalidly - * formatted. - * SRV_ERR 0x2 Server failure. Problem with NBNS, cannot - * process name. - * NAM_ERR 0x3 Name Error. The name requested does not - * exist. - * IMP_ERR 0x4 Unsupported request error. Allowable only - * for challenging NBNS when gets an Update type - * registration request. - * RFS_ERR 0x5 Refused error. For policy reasons server - * will not register this name from this host. - */ - -/* - * 4.2.15 REDIRECT NAME QUERY RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x0 |0|0|1|0|0 0|0| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0001 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NS (0x0002) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | RDLENGTH | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + - * | | - * / NSD_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | A (0x0001) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0004 | NSD_IP_ADDR | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NSD_IP_ADDR, continued | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * An end node responding to a NAME QUERY REQUEST always responds - * with the AA and RA bits set for both the NEGATIVE and POSITIVE - * NAME QUERY RESPONSE packets. An end node never sends a REDIRECT - * NAME QUERY RESPONSE packet. - * - * When the requestor receives the REDIRECT NAME QUERY RESPONSE it - * must reiterate the NAME QUERY REQUEST to the NBNS specified by - * the NSD_IP_ADDR field of the A type RESOURCE RECORD in the - * ADDITIONAL section of the response packet. This is an optional - * packet for the NBNS. - * - * The NSD_NAME and the RR_NAME in the ADDITIONAL section of the - * response packet are the same name. Space can be optimized if - * label string pointers are used in the RR_NAME which point to the - * labels in the NSD_NAME. - * - * The RR_NAME in the AUTHORITY section is the name of the domain - * the NBNS called by NSD_NAME has authority over. - */ - -/* - * 4.2.16 WAIT FOR ACKNOWLEDGEMENT (WACK) RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x7 |1|0|0|0|0 0|0| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NULL (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0002 | OPCODE | NM_FLAGS | 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * The NAME_TRN_ID of the WACK RESPONSE packet is the same - * NAME_TRN_ID of the request that the NBNS is telling the requestor - * to wait longer to complete. The RR_NAME is the name from the - * request, if any. If no name is available from the request then - * it is a null name, single byte of zero. - * - * The TTL field of the ResourceRecord is the new time to wait, in - * seconds, for the request to complete. The RDATA field contains - * the OPCODE and NM_FLAGS of the request. - * - * A TTL value of 0 means that the NBNS can not estimate the time it - * may take to complete a response. - */ - -/* - * 4.2.17 NODE STATUS REQUEST - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |0| 0x0 |0|0|0|0|0 0|B| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0001 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION_NAME / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NBSTAT (0x0021) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -/* - * 4.2.18 NODE STATUS RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x0 |1|0|0|0|0 0|0| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NBSTAT (0x0021) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x00000000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | RDLENGTH | NUM_NAMES | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + - * | | - * + + - * / NODE_NAME ARRAY / - * + + - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * + + - * / STATISTICS / - * + + - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * The NODE_NAME ARRAY is an array of zero or more NUM_NAMES entries - * of NODE_NAME records. Each NODE_NAME entry represents an active - * name in the same NetBIOS scope as the requesting name in the - * local name table of the responder. RR_NAME is the requesting - * name. - */ - #include <stdio.h> #include <synch.h> #include <pthread.h> @@ -963,14 +41,14 @@ #define QUEUE_INSERT_TAIL(q, e) \ ((e)->back) = (void *)((q)->back); \ - ((e)->forw) = (void *)(q); \ + ((e)->forw) = (void *)(q); \ ((q)->back->forw) = (void *)(e); \ ((q)->back) = (void *)(e); #define QUEUE_CLIP(e) \ (e)->forw->back = (e)->back; \ (e)->back->forw = (e)->forw; \ - (e)->forw = 0; \ + (e)->forw = 0; \ (e)->back = 0; #define NETBIOS_NAME_SVC_LAUNCHED 0x00001 @@ -994,6 +72,11 @@ char smb_node_type; +#define SMB_NODETYPE_B 'B' +#define SMB_NODETYPE_P 'P' +#define SMB_NODETYPE_M 'M' +#define SMB_NODETYPE_H 'H' + typedef struct { mutex_t mtx; cond_t cv; @@ -1082,7 +165,7 @@ typedef struct name_entry { unsigned short attributes; struct addr_entry addr_list; mutex_t mtx; -} name_entry; +} name_entry_t; struct name_question { struct name_entry *name; @@ -1523,6 +606,11 @@ typedef struct name_queue { mutex_t mtx; } name_queue_t; +typedef struct nbcache_iter { + HT_ITERATOR nbc_hti; + struct name_entry *nbc_entry; +} nbcache_iter_t; + #define NETBIOS_EMPTY_NAME (unsigned char *)"" #define NETBIOS_NAME_IS_STAR(name) \ @@ -1536,13 +624,11 @@ void smb_netbios_chg_status(uint32_t status, int set); int smb_netbios_cache_init(void); void smb_netbios_cache_fini(void); void smb_netbios_cache_dump(void); -void smb_netbios_cache_print(void); -void smb_netbios_cache_diag(char ** pbuf); int smb_netbios_cache_count(void); void smb_netbios_cache_clean(void); void smb_netbios_cache_reset_ttl(void); -void smb_netbios_cache_delete_locals(name_queue_t *delq); -void smb_netbios_cache_refresh(name_queue_t *refq); +void smb_netbios_cache_delete_locals(name_queue_t *); +void smb_netbios_cache_refresh(name_queue_t *); int smb_netbios_cache_insert(struct name_entry *name); int smb_netbios_cache_insert_list(struct name_entry *name); @@ -1550,23 +636,21 @@ void smb_netbios_cache_delete(struct name_entry *name); int smb_netbios_cache_delete_addr(struct name_entry *name); struct name_entry *smb_netbios_cache_lookup(struct name_entry *name); struct name_entry *smb_netbios_cache_lookup_addr(struct name_entry *name); -void smb_netbios_cache_update_entry(struct name_entry *entry, - struct name_entry *name); -void smb_netbios_cache_unlock_entry(struct name_entry *name); -unsigned char *smb_netbios_cache_status(unsigned char *buf, int bufsize, - unsigned char *scope); +void smb_netbios_cache_update_entry(struct name_entry *, struct name_entry *); +void smb_netbios_cache_unlock_entry(struct name_entry *); +unsigned char *smb_netbios_cache_status(unsigned char *, int, unsigned char *); +int smb_netbios_cache_getfirst(nbcache_iter_t *); +int smb_netbios_cache_getnext(nbcache_iter_t *); void smb_netbios_name_dump(struct name_entry *entry); void smb_netbios_name_logf(struct name_entry *entry); void smb_netbios_name_freeaddrs(struct name_entry *entry); -struct name_entry *smb_netbios_name_dup(struct name_entry *entry, - int alladdr); +struct name_entry *smb_netbios_name_dup(struct name_entry *, int); /* Name service functions */ void *smb_netbios_name_service_daemon(void *); -void smb_init_name_struct(unsigned char *, char, - unsigned char *, uint32_t, unsigned short, - uint32_t, uint32_t, struct name_entry *); +void smb_init_name_struct(unsigned char *, char, unsigned char *, uint32_t, + unsigned short, uint32_t, uint32_t, struct name_entry *); struct name_entry *smb_name_find_name(struct name_entry *name); int smb_name_add_name(struct name_entry *name); @@ -1577,41 +661,24 @@ void smb_netbios_name_config(void); void smb_netbios_name_unconfig(void); void smb_netbios_name_tick(void); -int smb_first_level_name_encode(struct name_entry *name, - unsigned char *out, int max_out); -int smb_first_level_name_decode(unsigned char *in, - struct name_entry *name); -void smb_encode_netbios_name(unsigned char *name, - char suffix, unsigned char *scope, - struct name_entry *dest); +int smb_first_level_name_encode(struct name_entry *, unsigned char *, int); +int smb_first_level_name_decode(unsigned char *, struct name_entry *); +void smb_encode_netbios_name(unsigned char *, char, unsigned char *, + struct name_entry *); /* Datagram service functions */ void *smb_netbios_datagram_service_daemon(void *); int smb_netbios_datagram_send(struct name_entry *, - struct name_entry *, unsigned char *, int); + struct name_entry *, unsigned char *, int); void smb_netbios_datagram_tick(void); - /* browser functions */ -void smb_browser_config(void); void *smb_browser_dispatch(void *arg); void *smb_browser_daemon(void *); -int smb_net_id(uint32_t ipaddr); -struct name_entry *smb_browser_get_srvname(unsigned short netid); -int smb_browser_load_transact_header(unsigned char *buffer, - int maxcnt, int data_count, int reply, char *mailbox); +int smb_browser_load_transact_header(unsigned char *, int, int, int, char *); /* Netlogon function */ -/* - * smb_netlogon_receive - * - * This is where we handle all incoming NetLogon messages. Currently, we - * ignore requests from anyone else. We are only interested in responses - * to our own requests. The NetLogonResponse provides the name of the PDC. - * If we don't already have a controller name, we use the name provided - * in the message. Otherwise we use the name already in the environment. - */ -void smb_netlogon_receive(struct datagram *datagram, char *mailbox, - unsigned char *data, int datalen); +void smb_netlogon_receive(struct datagram *, char *, unsigned char *, int); +void smb_netlogon_request(struct name_entry *, int, char *); #endif /* _SMB_NETBIOS_H_ */ diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c index a1c3bb2c03..dae42d4d7f 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c @@ -77,7 +77,7 @@ smb_netbios_cache_init() } void -smb_netbios_cache_fini() +smb_netbios_cache_fini(void) { (void) rw_wrlock(&nb_cache_lock); ht_destroy_table(smb_netbios_cache); @@ -86,13 +86,59 @@ smb_netbios_cache_fini() } void -smb_netbios_cache_clean() +smb_netbios_cache_clean(void) { (void) rw_wrlock(&nb_cache_lock); (void) ht_clean_table(smb_netbios_cache); (void) rw_unlock(&nb_cache_lock); } +int +smb_netbios_cache_getfirst(nbcache_iter_t *iter) +{ + HT_ITEM *item; + struct name_entry *entry; + + (void) rw_rdlock(&nb_cache_lock); + item = ht_findfirst(smb_netbios_cache, &iter->nbc_hti); + if (item == NULL || item->hi_data == NULL) { + (void) rw_unlock(&nb_cache_lock); + return (-1); + } + + entry = (struct name_entry *)item->hi_data; + (void) mutex_lock(&entry->mtx); + iter->nbc_entry = smb_netbios_name_dup(entry, 1); + (void) mutex_unlock(&entry->mtx); + + (void) rw_unlock(&nb_cache_lock); + + return ((iter->nbc_entry) ? 0 : -1); +} + +int +smb_netbios_cache_getnext(nbcache_iter_t *iter) +{ + HT_ITEM *item; + struct name_entry *entry; + + (void) rw_rdlock(&nb_cache_lock); + item = ht_findnext(&iter->nbc_hti); + if (item == NULL || item->hi_data == NULL) { + (void) rw_unlock(&nb_cache_lock); + return (-1); + } + + entry = (struct name_entry *)item->hi_data; + (void) mutex_lock(&entry->mtx); + iter->nbc_entry = smb_netbios_name_dup(entry, 1); + (void) mutex_unlock(&entry->mtx); + + (void) rw_unlock(&nb_cache_lock); + + return ((iter->nbc_entry) ? 0 : -1); +} + /* * smb_netbios_cache_lookup * @@ -106,19 +152,15 @@ smb_netbios_cache_lookup(struct name_entry *name) HT_ITEM *item; nb_key_t key; struct name_entry *entry = NULL; - unsigned char scope[SMB_PI_MAX_SCOPE]; unsigned char hostname[MAXHOSTNAMELEN]; if (NETBIOS_NAME_IS_STAR(name->name)) { /* Return our address */ - (void) smb_config_getstr(SMB_CI_NBSCOPE, (char *)scope, - sizeof (scope)); - (void) utf8_strupr((char *)scope); - - if (smb_getnetbiosname((char *)hostname, MAXHOSTNAMELEN) != 0) + if (smb_getnetbiosname((char *)hostname, sizeof (hostname)) + != 0) return (NULL); - smb_encode_netbios_name(hostname, 0x00, scope, name); + smb_encode_netbios_name(hostname, 0x00, NULL, name); } (void) rw_rdlock(&nb_cache_lock); @@ -196,6 +238,7 @@ smb_netbios_cache_insert(struct name_entry *name) struct addr_entry *name_addr; HT_ITEM *item; nb_key_t key; + int rc; /* No point in adding a name with IP address 255.255.255.255 */ if (name->addr_list.sin.sin_addr.s_addr == 0xffffffff) @@ -216,10 +259,9 @@ smb_netbios_cache_insert(struct name_entry *name) (addr->sin.sin_port == name_addr->sin.sin_port)) { entry->attributes |= name_addr->attributes & NAME_ATTR_LOCAL; - syslog(LOG_DEBUG, "cache_insert: exists"); (void) mutex_unlock(&entry->mtx); (void) rw_unlock(&nb_cache_lock); - return (0); /* exists */ + return (0); } /* Was not primary: looks for others */ @@ -227,32 +269,31 @@ smb_netbios_cache_insert(struct name_entry *name) addr != &entry->addr_list; addr = addr->forw) { if (NETBIOS_SAME_IP(addr, name_addr) && (addr->sin.sin_port == name_addr->sin.sin_port)) { - syslog(LOG_DEBUG, "cache_insert: dup"); (void) mutex_unlock(&entry->mtx); (void) rw_unlock(&nb_cache_lock); - return (0); /* exists */ + return (0); } } - addr = (struct addr_entry *)malloc(sizeof (struct addr_entry)); - if (addr == 0) { - (void) mutex_unlock(&entry->mtx); - (void) rw_unlock(&nb_cache_lock); - return (-1); + if ((addr = malloc(sizeof (struct addr_entry))) != NULL) { + *addr = name->addr_list; + entry->attributes |= addr->attributes; + QUEUE_INSERT_TAIL(&entry->addr_list, addr); + rc = 0; + } else { + rc = -1; } - *addr = name->addr_list; - entry->attributes |= addr->attributes; - QUEUE_INSERT_TAIL(&entry->addr_list, addr); + (void) mutex_unlock(&entry->mtx); (void) rw_unlock(&nb_cache_lock); - return (0); + return (rc); } - entry = (struct name_entry *)malloc(sizeof (struct name_entry)); - if (entry == 0) { + if ((entry = malloc(sizeof (struct name_entry))) == NULL) { (void) rw_unlock(&nb_cache_lock); return (-1); } + *entry = *name; entry->addr_list.forw = entry->addr_list.back = &entry->addr_list; entry->attributes |= entry->addr_list.attributes; diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c index 2775ccfe7a..c280a89e28 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -323,7 +323,6 @@ smb_netbios_datagram_send(struct name_entry *src, struct name_entry *dest, char *buffer; char ha_source[NETBIOS_DOMAIN_NAME_MAX]; char ha_dest[NETBIOS_DOMAIN_NAME_MAX]; - net_cfg_t cfg; (void) smb_first_level_name_encode(src, (unsigned char *)ha_source, sizeof (ha_source)); @@ -378,9 +377,8 @@ smb_netbios_datagram_send(struct name_entry *src, struct name_entry *dest, do { ipaddr = addr->sin.sin_addr.s_addr; /* Don't send anything to myself... */ - if (smb_nic_get_byip(ipaddr, &cfg) != NULL) { + if (smb_nic_exists(ipaddr, B_FALSE)) goto next; - } sin.sin_addr.s_addr = ipaddr; sin.sin_port = addr->sin.sin_port; @@ -405,7 +403,6 @@ smb_netbios_datagram_send_to_net(struct name_entry *src, char *buffer; char ha_source[NETBIOS_DOMAIN_NAME_MAX]; char ha_dest[NETBIOS_DOMAIN_NAME_MAX]; - net_cfg_t cfg; (void) smb_first_level_name_encode(src, (unsigned char *)ha_source, sizeof (ha_source)); @@ -459,9 +456,9 @@ smb_netbios_datagram_send_to_net(struct name_entry *src, addr = &dest->addr_list; do { ipaddr = addr->sin.sin_addr.s_addr; - if (smb_nic_get_byip(ipaddr, &cfg) != NULL) { + if (smb_nic_exists(ipaddr, B_FALSE)) goto next; - } + sin.sin_addr.s_addr = ipaddr; sin.sin_port = addr->sin.sin_port; (void) sendto(datagram_sock, buffer, count, 0, @@ -954,7 +951,6 @@ smb_netbios_datagram_service_daemon(void *arg) struct sockaddr_in sin; struct datagram *datagram; int bytes, flag = 1; - net_cfg_t cfg; (void) mutex_lock(&smb_dgq_mtx); bzero(&smb_datagram_queue, sizeof (smb_datagram_queue)); @@ -1009,11 +1005,11 @@ ignore: bzero(&datagram->inaddr, sizeof (struct addr_entry)); } /* Ignore any incoming packets from myself... */ - if (smb_nic_get_byip( - datagram->inaddr.sin.sin_addr.s_addr, - &cfg) != NULL) { + if (smb_nic_exists(datagram->inaddr.sin.sin_addr.s_addr, + B_FALSE)) { goto ignore; } + if (smb_datagram_decode(datagram, bytes) < 0) goto ignore; diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c index f7794479ab..7054d4bfae 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c @@ -588,11 +588,10 @@ strnchr(const char *s, char c, int n) return (0); } -/*ARGSUSED*/ -static int +static boolean_t is_multihome(char *name) { - return ((smb_nic_get_num() > 1) ? 1 : 0); + return (smb_nic_getnum(name) > 1); } /* @@ -1976,9 +1975,11 @@ smb_send_name_query_response(struct addr_entry *addr, NAME_ATTR_OWNER_NODE_TYPE); BE_OUT16(scan, attr); scan += 2; - (void) memcpy(scan, &raddr->sin.sin_addr.s_addr, - sizeof (uint32_t)); - scan += 4; + + *scan++ = raddr->sin.sin_addr.s_addr; + *scan++ = raddr->sin.sin_addr.s_addr >> 8; + *scan++ = raddr->sin.sin_addr.s_addr >> 16; + *scan++ = raddr->sin.sin_addr.s_addr >> 24; answer.rdlength += 6; raddr = raddr->forw; @@ -2134,7 +2135,6 @@ smb_send_node_status_response(struct addr_entry *addr, unsigned char *scan; unsigned char *scan_end; unsigned char data[MAX_NETBIOS_REPLY_DATA_SIZE]; - net_cfg_t cfg; boolean_t scan_done = B_FALSE; bzero(&packet, sizeof (struct name_packet)); @@ -2162,10 +2162,10 @@ smb_send_node_status_response(struct addr_entry *addr, scan_end = data + MAX_NETBIOS_REPLY_DATA_SIZE; - if (smb_nic_get_bysubnet(addr->sin.sin_addr.s_addr, &cfg) == NULL) - net_ipaddr = 0; + if (smb_nic_exists(addr->sin.sin_addr.s_addr, B_TRUE)) + net_ipaddr = addr->sin.sin_addr.s_addr; else - net_ipaddr = cfg.ip; + net_ipaddr = 0; (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &max_connections); @@ -2575,9 +2575,11 @@ smb_name_Bnode_delete_name(struct name_entry *name) NAME_ATTR_OWNER_NODE_TYPE); BE_OUT16(scan, attr); scan += 2; - (void) memcpy(scan, &raddr->sin.sin_addr.s_addr, - sizeof (uint32_t)); - scan += 4; + + *scan++ = raddr->sin.sin_addr.s_addr; + *scan++ = raddr->sin.sin_addr.s_addr >> 8; + *scan++ = raddr->sin.sin_addr.s_addr >> 16; + *scan++ = raddr->sin.sin_addr.s_addr >> 24; additional.rdlength += 6; } while (raddr != &name->addr_list); @@ -3010,10 +3012,11 @@ smb_name_Pnode_delete_name(struct name_entry *name) NAME_ATTR_OWNER_NODE_TYPE); BE_OUT16(scan, attr); scan += 2; - BE_OUT32(scan, raddr->sin.sin_addr.s_addr); scan += 4; - (void) memcpy(scan, &raddr->sin.sin_addr.s_addr, - sizeof (uint32_t)); - scan += 4; + + *scan++ = raddr->sin.sin_addr.s_addr; + *scan++ = raddr->sin.sin_addr.s_addr >> 8; + *scan++ = raddr->sin.sin_addr.s_addr >> 16; + *scan++ = raddr->sin.sin_addr.s_addr >> 24; additional.rdlength = 6; raddr = raddr->forw; @@ -4472,9 +4475,7 @@ smb_netbios_worker(void *arg) if (packet->answer) smb_netbios_name_freeaddrs(packet->answer->name); free(packet); - } - else - { + } else { syslog(LOG_DEBUG, "SmbNBNS: error decoding received packet"); } @@ -4497,33 +4498,62 @@ smb_netbios_wins_config(char *ip) smb_nbns[nbns_num].sin.sin_addr.s_addr = ipaddr; smb_nbns[nbns_num++].sin.sin_port = htons(NAME_SERVICE_UDP_PORT); - smb_node_type = 'H'; + smb_node_type = SMB_NODETYPE_H; + } +} + +static void +smb_netbios_name_registration(void) +{ + nbcache_iter_t nbc_iter; + struct name_entry *name; + int rc; + + rc = smb_netbios_cache_getfirst(&nbc_iter); + while (rc == 0) { + name = nbc_iter.nbc_entry; + (void) smb_netbios_name_logf(name); + if (IS_UNIQUE(name->attributes) && IS_LOCAL(name->attributes)) { + switch (smb_node_type) { + case SMB_NODETYPE_B: + (void) smb_name_Bnode_add_name(name); + break; + case SMB_NODETYPE_P: + (void) smb_name_Pnode_add_name(name); + break; + case SMB_NODETYPE_M: + (void) smb_name_Mnode_add_name(name); + break; + case SMB_NODETYPE_H: + default: + (void) smb_name_Hnode_add_name(name); + break; + } + } + free(name); + rc = smb_netbios_cache_getnext(&nbc_iter); } } void smb_netbios_name_config(void) { - uint32_t ipaddr; struct name_entry name; - char myname[MAXHOSTNAMELEN]; - int i; - int smb_nc_cnt; - net_cfg_t cfg; char wins_ip[16]; - - if (smb_getnetbiosname(myname, MAXHOSTNAMELEN) != 0) - return; + smb_niciter_t ni; + int rc; /* Start with no broadcast addresses */ bcast_num = 0; bzero(smb_bcast_list, sizeof (addr_entry_t) * SMB_PI_MAX_NETWORKS); - smb_nc_cnt = smb_nic_get_num(); - /* Add all of my broadcast addresses */ - for (i = 0; i < smb_nc_cnt; i++) { - if (smb_nic_get_byind(i, &cfg) == NULL) { - break; + /* Add all of the broadcast addresses */ + rc = smb_nic_getfirst(&ni); + while (rc == 0) { + if (ni.ni_nic.nic_smbflags & + (SMB_NICF_ALIAS | SMB_NICF_NBEXCL)) { + rc = smb_nic_getnext(&ni); + continue; } smb_bcast_list[bcast_num].flags = ADDR_FLAG_VALID; smb_bcast_list[bcast_num].attributes = NAME_ATTR_LOCAL; @@ -4532,11 +4562,12 @@ smb_netbios_name_config(void) smb_bcast_list[bcast_num].sin.sin_port = htons(NAME_SERVICE_UDP_PORT); smb_bcast_list[bcast_num++].sin.sin_addr.s_addr = - cfg.broadcast; + ni.ni_nic.nic_bcast; + rc = smb_nic_getnext(&ni); } /* Start with no WINS */ - smb_node_type = 'B'; + smb_node_type = SMB_NODETYPE_B; nbns_num = 0; bzero(smb_nbns, sizeof (addr_entry_t) * SMB_PI_MAX_WINS); @@ -4546,24 +4577,25 @@ smb_netbios_name_config(void) (void) smb_config_getstr(SMB_CI_WINS_SRV2, wins_ip, sizeof (wins_ip)); smb_netbios_wins_config(wins_ip); - for (i = 0; i < smb_nc_cnt; i++) { - if (smb_nic_get_byind(i, &cfg) == NULL) { - break; - } - if (cfg.exclude) + if (smb_nic_getfirst(&ni) != 0) + return; + + do { + if (ni.ni_nic.nic_smbflags & SMB_NICF_NBEXCL) continue; - ipaddr = cfg.ip; - smb_init_name_struct((unsigned char *)myname, 0x00, 0, ipaddr, - htons(DGM_SRVC_UDP_PORT), NAME_ATTR_UNIQUE, - NAME_ATTR_LOCAL, &name); - (void) smb_name_add_name(&name); + smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host, + 0x00, 0, ni.ni_nic.nic_ip, htons(DGM_SRVC_UDP_PORT), + NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &name); + (void) smb_netbios_cache_insert(&name); - smb_init_name_struct((unsigned char *)myname, 0x20, 0, - ipaddr, htons(DGM_SRVC_UDP_PORT), + smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host, + 0x20, 0, ni.ni_nic.nic_ip, htons(DGM_SRVC_UDP_PORT), NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &name); - (void) smb_name_add_name(&name); - } + (void) smb_netbios_cache_insert(&name); + } while (smb_nic_getnext(&ni) == 0); + + smb_netbios_name_registration(); } void @@ -4612,7 +4644,6 @@ smb_netbios_name_service_daemon(void *arg) int flag = 1; char *buf; worker_param_t *worker_param; - net_cfg_t cfg; /* * Initialize reply_queue @@ -4689,10 +4720,8 @@ ignore: bzero(addr, sizeof (struct addr_entry)); } /* Ignore any incoming packets from myself... */ - if (smb_nic_get_byip(addr->sin.sin_addr.s_addr, - &cfg) != NULL) { + if (smb_nic_exists(addr->sin.sin_addr.s_addr, B_FALSE)) goto ignore; - } /* * Launch a netbios worker to process the received packet. diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c index 2631bd0f68..6f99711a7c 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c @@ -74,29 +74,24 @@ static char resource_domain[SMB_PI_MAX_DOMAIN]; * in smb_netlogon_receive. */ void -smb_netlogon_request(int net, int protocol, char *domain) +smb_netlogon_request(struct name_entry *server, int protocol, char *domain) { - struct name_entry *server; nt_domain_t *ntdp; - server = smb_browser_get_srvname(net); - if (server == 0) + if (domain == NULL || *domain == '\0') return; - (void) strlcpy(resource_domain, domain, - sizeof (resource_domain)); - - if (strlen(resource_domain) > 0) { - ntdp = nt_domain_lookup_name(resource_domain); - if (protocol == NETLOGON_PROTO_SAMLOGON && ntdp) - smb_netlogon_samlogon(server, - MAILSLOT_NETLOGON_SAMLOGON_RDC, - resource_domain); - else - smb_netlogon_query(server, - MAILSLOT_NETLOGON_RDC, - resource_domain); - } + (void) strlcpy(resource_domain, domain, sizeof (resource_domain)); + + ntdp = nt_domain_lookup_name(resource_domain); + if (ntdp && (protocol == NETLOGON_PROTO_SAMLOGON)) + smb_netlogon_samlogon(server, + MAILSLOT_NETLOGON_SAMLOGON_RDC, + resource_domain); + else + smb_netlogon_query(server, + MAILSLOT_NETLOGON_RDC, + resource_domain); } /* @@ -521,8 +516,6 @@ smb_netlogon_rdc_rsp(char *src_name, uint32_t src_ipaddr) static int better_dc(uint32_t cur_ip, uint32_t new_ip) { - net_cfg_t cfg; - /* * If we don't have any current DC, * then use the new one of course. @@ -530,9 +523,10 @@ better_dc(uint32_t cur_ip, uint32_t new_ip) if (cur_ip == 0) return (1); - if (smb_nic_get_bysubnet(cur_ip, &cfg) != NULL) + if (smb_nic_exists(cur_ip, B_TRUE)) return (0); - if (smb_nic_get_bysubnet(new_ip, &cfg) != NULL) + + if (smb_nic_exists(new_ip, B_TRUE)) return (1); /* * Otherwise, just keep the old one. diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c deleted file mode 100644 index fc812e2567..0000000000 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * 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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <syslog.h> -#include <libintl.h> -#include <strings.h> -#include <unistd.h> -#include <synch.h> -#include <stropts.h> -#include <errno.h> -#include <pthread.h> - -#include <inet/ip.h> -#include <net/if.h> -#include <netinet/in.h> -#include <netdb.h> -#include <net/route.h> -#include <arpa/inet.h> -#include <arpa/nameser.h> -#include <resolv.h> - -#include <sys/socket.h> -#include <sys/sockio.h> -#include <sys/systeminfo.h> - -#include <smbsrv/libsmbns.h> - -#define MAXIFS 256 - -typedef struct smb_ifnames { - char *if_names[MAXIFS]; - int if_num; -} smb_ifnames_t; - -typedef struct { - net_cfg_t *nl_nics; - int nl_cnt; -} smb_niclist_t; - -static int smb_nic_iflist_create(smb_ifnames_t *); -static void smb_nic_iflist_destroy(smb_ifnames_t *); - -static int smb_niclist_create(void); -static void smb_niclist_destroy(void); -static void smb_niclist_lock(void); -static void smb_niclist_unlock(void); - -/* This is the list we will monitor */ -static smb_niclist_t smb_niclist = { NULL, 0 }; -static pthread_mutex_t smb_niclist_mtx = PTHREAD_MUTEX_INITIALIZER; - -int -smb_get_nameservers(struct in_addr *ips, int sz) -{ - union res_sockaddr_union set[MAXNS]; - int i, cnt; - struct __res_state res_state; - - if (ips == NULL) - return (0); - - bzero(&res_state, sizeof (struct __res_state)); - if (res_ninit(&res_state) < 0) - return (0); - - cnt = res_getservers(&res_state, set, MAXNS); - for (i = 0; i < cnt; i++) { - if (i >= sz) - break; - ips[i] = set[i].sin.sin_addr; - syslog(LOG_DEBUG, "NS Found %s name server\n", - inet_ntoa(ips[i])); - } - syslog(LOG_DEBUG, "NS Found %d name servers\n", i); - res_ndestroy(&res_state); - return (i); -} - -/* - * Initialize interface list. - */ -void -smb_nic_build_info(void) -{ - smb_niclist_lock(); - smb_niclist_destroy(); - - if (smb_niclist_create() < 0) - syslog(LOG_ERR, "smbd: failed getting network interfaces" - " information"); - else if (smb_niclist.nl_cnt == 0) - syslog(LOG_ERR, "smbd: No network interfaces are configured " - "smb server may not function properly"); - - smb_niclist_unlock(); -} - -/* - * Get number of interfaces. - */ -int -smb_nic_get_num(void) -{ - int n; - - smb_niclist_lock(); - n = smb_niclist.nl_cnt; - smb_niclist_unlock(); - - return (n); -} - -/* - * Get if by index - * Returns: NULL if not found. - */ -net_cfg_t * -smb_nic_get_byind(int ind, net_cfg_t *cfg) -{ - if (cfg == NULL) - return (NULL); - - smb_niclist_lock(); - if (ind > smb_niclist.nl_cnt) { - smb_niclist_unlock(); - return (NULL); - } - bcopy(&smb_niclist.nl_nics[ind], cfg, sizeof (net_cfg_t)); - smb_niclist_unlock(); - - return (cfg); -} - -/* - * Get if by subnet - * Returns: NULL if not found. - */ -net_cfg_t * -smb_nic_get_bysubnet(uint32_t ipaddr, net_cfg_t *cfg) -{ - net_cfg_t *tcfg; - int i; - - if (cfg == NULL) - return (NULL); - - bzero(cfg, sizeof (net_cfg_t)); - - smb_niclist_lock(); - for (i = 0; i < smb_niclist.nl_cnt; i++) { - tcfg = &smb_niclist.nl_nics[i]; - if ((ipaddr & tcfg->mask) == - (tcfg->ip & tcfg->mask)) { - bcopy(tcfg, cfg, sizeof (net_cfg_t)); - smb_niclist_unlock(); - return (cfg); - } - } - smb_niclist_unlock(); - - return (NULL); -} - -/* - * Get if by ip. - * Returns: NULL if not found. - */ -net_cfg_t * -smb_nic_get_byip(uint32_t ipaddr, net_cfg_t *cfg) -{ - net_cfg_t *tcfg; - int i; - - if (cfg == NULL) - return (NULL); - - bzero(cfg, sizeof (net_cfg_t)); - - smb_niclist_lock(); - for (i = 0; i < smb_niclist.nl_cnt; i++) { - tcfg = &smb_niclist.nl_nics[i]; - if (ipaddr == tcfg->ip) { - bcopy(tcfg, cfg, sizeof (net_cfg_t)); - smb_niclist_unlock(); - return (cfg); - } - } - smb_niclist_unlock(); - - return (NULL); -} - -/* - * The following list is taken from if.h. The function takes the - * given interface name, and the passed flag(s), and returns true if - * the flag is associated with the interface, and false if not. - * - * IFF_UP interface is up - * IFF_BROADCAST broadcast address valid - * IFF_LOOPBACK is a loopback net - * IFF_POINTOPOINT interface is point-to-point link - * IFF_RUNNING resources allocated - * IFF_MULTICAST supports multicast - * IFF_MULTI_BCAST multicast using broadcast address - * IFF_UNNUMBERED non-unique address - * IFF_DHCPRUNNING DHCP controls this interface - * IFF_PRIVATE do not advertise - * IFF_DEPRECATED interface address deprecated - * IFF_ANYCAST Anycast address - * IFF_IPV4 IPv4 interface - * IFF_IPV6 IPv6 interface - * IFF_NOFAILOVER Don't failover on NIC failure - * IFF_FAILED NIC has failed - * IFF_STANDBY Standby NIC to be used on failures - * IFF_OFFLINE NIC has been offlined - */ -boolean_t -smb_nic_status(char *interface, uint64_t flag) -{ - struct lifreq lifrr; - int rc; - int s; - - if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { - syslog(LOG_DEBUG, "smb_nic_status: %s", strerror(errno)); - return (B_FALSE); - } - - (void) strlcpy(lifrr.lifr_name, interface, sizeof (lifrr.lifr_name)); - rc = ioctl(s, SIOCGLIFFLAGS, &lifrr); - (void) close(s); - - if (rc < 0) { - syslog(LOG_DEBUG, "smb_nic_status: %s", strerror(errno)); - return (B_FALSE); - } - - if (lifrr.lifr_flags & flag) - return (B_TRUE); - - return (B_FALSE); -} - -/* - * Get IP info and more for the given interface - */ -static int -smb_nic_getinfo(char *interface, net_cfg_t *nc) -{ - struct lifreq lifrr; - struct sockaddr_in *sa; - int s; - - if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { - return (-1); - } - - (void) strlcpy(lifrr.lifr_name, interface, sizeof (lifrr.lifr_name)); - if (ioctl(s, SIOCGLIFADDR, &lifrr) < 0) { - (void) close(s); - return (-1); - } - sa = (struct sockaddr_in *)&lifrr.lifr_addr; - nc->ip = (uint32_t)sa->sin_addr.s_addr; - - if (ioctl(s, SIOCGLIFBRDADDR, &lifrr) < 0) { - (void) close(s); - return (-1); - } - sa = (struct sockaddr_in *)&lifrr.lifr_broadaddr; - nc->broadcast = (uint32_t)sa->sin_addr.s_addr; - - if (ioctl(s, SIOCGLIFNETMASK, &lifrr) < 0) { - (void) close(s); - return (-1); - } - sa = (struct sockaddr_in *)&lifrr.lifr_addr; - nc->mask = (uint32_t)sa->sin_addr.s_addr; - - if (ioctl(s, SIOCGLIFFLAGS, &lifrr) < 0) { - (void) close(s); - return (-1); - } - nc->flags = lifrr.lifr_flags; - - (void) strlcpy(nc->ifname, interface, sizeof (nc->ifname)); - - (void) close(s); - return (0); -} - -/* - * Get the list of currently plumbed interface names. The loopback (lo0) - * port is ignored - */ -static int -smb_nic_iflist_create(smb_ifnames_t *iflist) -{ - struct ifconf ifc; - struct ifreq ifr; - struct ifreq *ifrp; - char *ifname; - int ifnum; - int i; - int s; - - bzero(iflist, sizeof (smb_ifnames_t)); - - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - return (-1); - - if (ioctl(s, SIOCGIFNUM, (char *)&ifnum) < 0) { - (void) close(s); - return (-1); - } - - ifc.ifc_len = ifnum * sizeof (struct ifreq); - ifc.ifc_buf = malloc(ifc.ifc_len); - if (ifc.ifc_buf == NULL) { - (void) close(s); - return (-1); - } - bzero(ifc.ifc_buf, ifc.ifc_len); - - if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { - (void) close(s); - free(ifc.ifc_buf); - return (-1); - } - - ifrp = ifc.ifc_req; - ifnum = ifc.ifc_len / sizeof (struct ifreq); - - for (i = 0; i < ifnum; i++, ifrp++) { - /* - * Get the flags so that we can skip the loopback interface - */ - (void) memset(&ifr, 0, sizeof (ifr)); - (void) strlcpy(ifr.ifr_name, ifrp->ifr_name, - sizeof (ifr.ifr_name)); - - if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { - (void) close(s); - free(ifc.ifc_buf); - smb_nic_iflist_destroy(iflist); - return (-1); - } - - if (ifr.ifr_flags & IFF_LOOPBACK) - continue; - - if ((ifr.ifr_flags & IFF_UP) == 0) - continue; - - ifname = strdup(ifrp->ifr_name); - if (ifname == NULL) { - (void) close(s); - free(ifc.ifc_buf); - smb_nic_iflist_destroy(iflist); - return (-1); - } - iflist->if_names[iflist->if_num++] = ifname; - } - - (void) close(s); - free(ifc.ifc_buf); - return (0); -} - -/* - * Frees allocated memory for the given IF names lists. - */ -static void -smb_nic_iflist_destroy(smb_ifnames_t *iflist) -{ - int i; - - if (iflist == NULL) - return; - - for (i = 0; i < iflist->if_num; i++) - free(iflist->if_names[i]); -} - -/* - * This will mimick the workings of ifconfig -a command. - * - * Note that the caller of this function should grab the - * list lock. - */ -static int -smb_niclist_create(void) -{ - smb_ifnames_t ifnames; - net_cfg_t *nc; - char *ifname; - char excludestr[MAX_EXCLUDE_LIST_LEN]; - ipaddr_t exclude[SMB_PI_MAX_NETWORKS]; - int nexclude; - int i; - - if (smb_nic_iflist_create(&ifnames) < 0) - return (-1); - - smb_niclist.nl_nics = calloc(ifnames.if_num, sizeof (net_cfg_t)); - if (smb_niclist.nl_nics == NULL) { - smb_nic_iflist_destroy(&ifnames); - return (-1); - } - - (void) smb_config_getstr(SMB_CI_WINS_EXCL, excludestr, - sizeof (excludestr)); - nexclude = smb_wins_iplist(excludestr, exclude, SMB_PI_MAX_NETWORKS); - - nc = smb_niclist.nl_nics; - for (i = 0; i < ifnames.if_num; i++, nc++) { - ifname = ifnames.if_names[i]; - if (strchr(ifname, ':')) - /* Will not provide info on logical interfaces */ - continue; - - if (smb_nic_getinfo(ifname, nc) < 0) { - smb_nic_iflist_destroy(&ifnames); - smb_niclist_destroy(); - return (-1); - } - smb_niclist.nl_cnt++; - - if (smb_wins_is_excluded(nc->ip, - (ipaddr_t *)exclude, nexclude)) - nc->exclude = B_TRUE; - } - - smb_nic_iflist_destroy(&ifnames); - - return (0); -} - -static void -smb_niclist_destroy(void) -{ - free(smb_niclist.nl_nics); - smb_niclist.nl_nics = NULL; - smb_niclist.nl_cnt = 0; -} - -/* - * smb_niclist_lock - * - * Lock the nic table - */ -static void -smb_niclist_lock(void) -{ - (void) pthread_mutex_lock(&smb_niclist_mtx); -} - -/* - * smb_niclist_unlock - * - * Unlock the nic table. - */ -static void -smb_niclist_unlock(void) -{ - (void) pthread_mutex_unlock(&smb_niclist_mtx); -} diff --git a/usr/src/uts/common/fs/smbsrv/smb_check_directory.c b/usr/src/uts/common/fs/smbsrv/smb_check_directory.c index 9d6d0c202d..b2ca8db4a5 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_check_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_check_directory.c @@ -67,7 +67,7 @@ #include <smbsrv/smb_incl.h> #include <smbsrv/smb_fsops.h> -int +smb_sdrc_t smb_com_check_directory(struct smb_request *sr) { int rc; @@ -76,20 +76,18 @@ smb_com_check_directory(struct smb_request *sr) if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - if (smbsr_decode_data(sr, "%S", sr, &sr->arg.dirop.fqi.path) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_data(sr, "%S", sr, &sr->arg.dirop.fqi.path) != 0) + return (SDRC_ERROR_REPLY); sr->arg.dirop.fqi.srch_attr = 0; rc = smbd_fs_query(sr, &sr->arg.dirop.fqi, FQM_PATH_MUST_EXIST); if (rc) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } /* @@ -105,7 +103,7 @@ smb_com_check_directory(struct smb_request *sr) SMB_NULL_FQI_NODES(sr->arg.dirop.fqi); smbsr_errno(sr, ENOTDIR); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } rc = smb_fsop_access(sr, sr->user_cr, dnode, FILE_TRAVERSE); @@ -116,10 +114,9 @@ smb_com_check_directory(struct smb_request *sr) if (rc != 0) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - smbsr_encode_empty_result(sr); - - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_close.c b/usr/src/uts/common/fs/smbsrv/smb_close.c index f2d7faeb8d..988ba3697d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_close.c +++ b/usr/src/uts/common/fs/smbsrv/smb_close.c @@ -39,54 +39,50 @@ * Failure to set the timestamp, even if requested by the client, * should not result in an error response from the server. */ -int +smb_sdrc_t smb_com_close(struct smb_request *sr) { uint32_t last_wtime; int rc = 0; rc = smbsr_decode_vwv(sr, "wl", &sr->smb_fid, &last_wtime); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } rc = smb_common_close(sr, last_wtime); if (rc) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - smbsr_encode_empty_result(sr); - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } /* * Close the file represented by fid and then disconnect the * associated tree. */ -int +smb_sdrc_t smb_com_close_and_tree_disconnect(struct smb_request *sr) { uint32_t last_wtime; int rc = 0; rc = smbsr_decode_vwv(sr, "wl", &sr->smb_fid, &last_wtime); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } rc = smb_common_close(sr, last_wtime); @@ -95,11 +91,11 @@ smb_com_close_and_tree_disconnect(struct smb_request *sr) if (rc) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - smbsr_encode_empty_result(sr); - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } /* diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_open.c b/usr/src/uts/common/fs/smbsrv/smb_common_open.c index 5e0d94976b..7b902a2835 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c @@ -39,7 +39,9 @@ #include <sys/fcntl.h> #include <sys/nbmlock.h> -extern uint32_t smb_is_executable(char *path); +extern uint32_t smb_is_executable(char *); + +static uint32_t smb_open_subr(smb_request_t *); /* * The default stability mode is to perform the write-through @@ -207,6 +209,42 @@ smb_ofun_to_crdisposition(uint16_t ofun) } /* + * Retry opens to avoid spurious sharing violations, due to timing + * issues between closes and opens. The client that already has the + * file open may be in the process of closing it. + */ +uint32_t +smb_common_open(smb_request_t *sr) +{ + uint32_t status = NT_STATUS_SUCCESS; + int count; + + for (count = 0; count <= 4; count++) { + if (count) + delay(MSEC_TO_TICK(400)); + + if ((status = smb_open_subr(sr)) == NT_STATUS_SUCCESS) + break; + } + + switch (status) { + case NT_STATUS_SUCCESS: + break; + + case NT_STATUS_SHARING_VIOLATION: + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, + ERRDOS, ERROR_SHARING_VIOLATION); + break; + + default: + /* Error already set. */ + break; + } + + return (status); +} + +/* * smb_open_subr * * Notes on write-through behaviour. It looks like pre-LM0.12 versions @@ -229,8 +267,8 @@ smb_ofun_to_crdisposition(uint16_t ofun) * handle things in here. */ -uint32_t -smb_open_subr(struct smb_request *sr) +static uint32_t +smb_open_subr(smb_request_t *sr) { int created = 0; struct smb_node *node = 0; @@ -247,7 +285,7 @@ smb_open_subr(struct smb_request *sr) uint32_t status = NT_STATUS_SUCCESS; int is_dir; smb_error_t err; - int is_stream; + int is_stream = 0; int lookup_flags = SMB_FOLLOW_LINKS; uint32_t daccess; uint32_t share_access = op->share_access; @@ -257,17 +295,16 @@ smb_open_subr(struct smb_request *sr) if (is_dir) { /* - * The file being created or opened is a directory file. - * With this flag, the Disposition parameter must be set to - * one of FILE_CREATE, FILE_OPEN, or FILE_OPEN_IF + * The object being created or opened is a directory, + * and the Disposition parameter must be one of + * FILE_CREATE, FILE_OPEN, or FILE_OPEN_IF */ if ((op->create_disposition != FILE_CREATE) && (op->create_disposition != FILE_OPEN_IF) && (op->create_disposition != FILE_OPEN)) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_ACCESS); - /* invalid open mode */ - /* NOTREACHED */ + return (NT_STATUS_INVALID_PARAMETER); } } @@ -278,7 +315,6 @@ smb_open_subr(struct smb_request *sr) op->desired_access = smb_access_generic_to_file(op->desired_access); if (sr->session->s_file_cnt >= SMB_SESSION_OFILE_MAX) { - ASSERT(sr->uid_user); cmn_err(CE_NOTE, "smbd[%s\\%s]: %s", sr->uid_user->u_domain, sr->uid_user->u_name, @@ -286,7 +322,7 @@ smb_open_subr(struct smb_request *sr) smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES, ERRDOS, ERROR_TOO_MANY_OPEN_FILES); - /* NOTREACHED */ + return (NT_STATUS_TOO_MANY_OPENED_FILES); } /* This must be NULL at this point */ @@ -303,23 +339,19 @@ smb_open_subr(struct smb_request *sr) * No further processing for IPC, we need to either * raise an exception or return success here. */ - if ((rc = smb_rpc_open(sr)) != 0) { - smbsr_error(sr, rc, 0, 0); - /* NOTREACHED */ - } else { - return (NT_STATUS_SUCCESS); - } - break; + if ((status = smb_rpc_open(sr)) != NT_STATUS_SUCCESS) + smbsr_error(sr, status, 0, 0); + return (status); default: - smbsr_error(sr, 0, ERRSRV, ERRinvdevice); - /* NOTREACHED */ - break; + smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, + ERRDOS, ERROR_BAD_DEV_TYPE); + return (NT_STATUS_BAD_DEVICE_TYPE); } if ((pathlen = strlen(op->fqi.path)) >= MAXPATHLEN) { smbsr_error(sr, 0, ERRSRV, ERRfilespecs); - /* NOTREACHED */ + return (NT_STATUS_NAME_TOO_LONG); } /* @@ -334,7 +366,7 @@ smb_open_subr(struct smb_request *sr) if ((status = smb_validate_object_name(op->fqi.path, is_dir)) != 0) { smbsr_error(sr, status, ERRDOS, ERROR_INVALID_NAME); - /* NOTREACHED */ + return (status); } cur_node = op->fqi.dir_snode ? @@ -344,7 +376,7 @@ smb_open_subr(struct smb_request *sr) sr->tid_tree->t_snode, cur_node, &op->fqi.dir_snode, op->fqi.last_comp)) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (sr->smb_error.status); } /* @@ -376,7 +408,7 @@ smb_open_subr(struct smb_request *sr) smb_node_release(op->fqi.dir_snode); SMB_NULL_FQI_NODES(op->fqi); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (sr->smb_error.status); } /* @@ -411,7 +443,7 @@ smb_open_subr(struct smb_request *sr) SMB_NULL_FQI_NODES(op->fqi); smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (NT_STATUS_FILE_IS_A_DIRECTORY); } if (op->fqi.last_attr.sa_vattr.va_type == VDIR) { @@ -427,7 +459,7 @@ smb_open_subr(struct smb_request *sr) SMB_NULL_FQI_NODES(op->fqi); smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (NT_STATUS_FILE_IS_A_DIRECTORY); } } else if (op->my_flags & MYF_MUST_BE_DIRECTORY) { rw_exit(&node->n_share_lock); @@ -436,7 +468,7 @@ smb_open_subr(struct smb_request *sr) SMB_NULL_FQI_NODES(op->fqi); smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY, ERRDOS, ERROR_DIRECTORY); - /* NOTREACHED */ + return (NT_STATUS_NOT_A_DIRECTORY); } /* @@ -450,7 +482,7 @@ smb_open_subr(struct smb_request *sr) SMB_NULL_FQI_NODES(op->fqi); smbsr_error(sr, NT_STATUS_DELETE_PENDING, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (NT_STATUS_DELETE_PENDING); } /* @@ -463,7 +495,7 @@ smb_open_subr(struct smb_request *sr) SMB_NULL_FQI_NODES(op->fqi); smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION, ERRDOS, ERROR_ALREADY_EXISTS); - /* NOTREACHED */ + return (NT_STATUS_OBJECT_NAME_COLLISION); } /* @@ -481,7 +513,7 @@ smb_open_subr(struct smb_request *sr) SMB_NULL_FQI_NODES(op->fqi); smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); - /* NOTREACHED */ + return (NT_STATUS_ACCESS_DENIED); } } } @@ -503,6 +535,7 @@ smb_open_subr(struct smb_request *sr) SMB_NULL_FQI_NODES(op->fqi); smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); + return (NT_STATUS_ACCESS_DENIED); } } @@ -531,9 +564,11 @@ smb_open_subr(struct smb_request *sr) if (status == NT_STATUS_PRIVILEGE_NOT_HELD) { smbsr_error(sr, status, ERRDOS, ERROR_PRIVILEGE_NOT_HELD); + return (status); } else { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); + return (NT_STATUS_ACCESS_DENIED); } } @@ -553,7 +588,7 @@ smb_open_subr(struct smb_request *sr) SMB_NULL_FQI_NODES(op->fqi); smbsr_error(sr, status, ERRDOS, ERROR_VC_DISCONNECTED); - /* NOTREACHED */ + return (status); } } @@ -569,7 +604,7 @@ smb_open_subr(struct smb_request *sr) SMB_NULL_FQI_NODES(op->fqi); smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (NT_STATUS_ACCESS_DENIED); } if (node->attr.sa_vattr.va_size != op->dsize) { @@ -589,7 +624,7 @@ smb_open_subr(struct smb_request *sr) smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (sr->smb_error.status); } op->dsize = op->fqi.last_attr.sa_vattr.va_size; @@ -618,13 +653,15 @@ smb_open_subr(struct smb_request *sr) /* Last component was not found. */ dnode = op->fqi.dir_snode; + if (is_dir == 0) + is_stream = smb_stream_parse_name(op->fqi.path, + NULL, NULL); + if ((op->create_disposition == FILE_OPEN) || (op->create_disposition == FILE_OVERWRITE)) { smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - is_stream = smb_stream_parse_name(op->fqi.path, - NULL, NULL); /* * The requested file not found so the operation should * fail with these two dispositions @@ -634,7 +671,8 @@ smb_open_subr(struct smb_request *sr) ERRDOS, ERROR_FILE_NOT_FOUND); else smbsr_error(sr, 0, ERRDOS, ERRbadfile); - /* NOTREACHED */ + + return (NT_STATUS_OBJECT_NAME_NOT_FOUND); } /* @@ -646,7 +684,9 @@ smb_open_subr(struct smb_request *sr) bzero(&new_attr, sizeof (new_attr)); if (is_dir == 0) { new_attr.sa_vattr.va_type = VREG; - new_attr.sa_vattr.va_mode = 0666; + new_attr.sa_vattr.va_mode = is_stream ? S_IRUSR : + S_IRUSR | S_IRGRP | S_IROTH | + S_IWUSR | S_IWGRP | S_IWOTH; new_attr.sa_mask = SMB_AT_TYPE | SMB_AT_MODE; /* @@ -678,7 +718,7 @@ smb_open_subr(struct smb_request *sr) smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (sr->smb_error.status); } if (op->dattr & SMB_FA_READONLY) { @@ -732,7 +772,7 @@ smb_open_subr(struct smb_request *sr) smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (sr->smb_error.status); } else { op->fqi.last_attr = node->attr; } @@ -751,7 +791,7 @@ smb_open_subr(struct smb_request *sr) smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (sr->smb_error.status); } node = op->fqi.last_snode; @@ -777,7 +817,7 @@ smb_open_subr(struct smb_request *sr) smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); - /* NOTREACHED */ + return (NT_STATUS_ACCESS_DENIED); } if (max_requested) { @@ -806,7 +846,7 @@ smb_open_subr(struct smb_request *sr) smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); smbsr_error(sr, err.status, err.errcls, err.errcode); - /* NOTREACHED */ + return (err.status); } /* @@ -846,7 +886,7 @@ smb_open_subr(struct smb_request *sr) smbsr_error(sr, status, ERRDOS, ERROR_SHARING_VIOLATION); - /* NOTREACHED */ + return (status); } op->my_flags |= granted_oplock; diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_search.c b/usr/src/uts/common/fs/smbsrv/smb_common_search.c index 84d35fe9b0..b5fb122791 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_search.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_search.c @@ -41,8 +41,7 @@ smb_rdir_open(smb_request_t *sr, char *path, unsigned short sattr) smb_odir_t *od; smb_node_t *node; char *last_component; - unsigned int rc; - int erc; + int rc; last_component = kmem_alloc(MAXNAMELEN, KM_SLEEP); @@ -51,28 +50,29 @@ smb_rdir_open(smb_request_t *sr, char *path, unsigned short sattr) &node, last_component)) != 0) { kmem_free(last_component, MAXNAMELEN); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (-1); } if ((node->vp)->v_type != VDIR) { smb_node_release(node); kmem_free(last_component, MAXNAMELEN); smbsr_error(sr, 0, ERRDOS, ERRbadpath); - /* NOTREACHED */ + return (-1); } - erc = smb_fsop_access(sr, sr->user_cr, node, FILE_LIST_DIRECTORY); - if (erc != 0) { + rc = smb_fsop_access(sr, sr->user_cr, node, FILE_LIST_DIRECTORY); + if (rc != 0) { smb_node_release(node); kmem_free(last_component, MAXNAMELEN); + if (sr->smb_com == SMB_COM_SEARCH) { smbsr_warn(sr, NT_STATUS_NO_MORE_FILES, ERRDOS, ERROR_NO_MORE_FILES); - return (SDRC_NORMAL_REPLY); + return (-2); } else { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (-1); } } @@ -82,13 +82,12 @@ smb_rdir_open(smb_request_t *sr, char *path, unsigned short sattr) if (od == NULL) { smb_node_release(node); smbsr_error(sr, 0, ERRDOS, ERROR_NO_MORE_FILES); - /* NOTREACHED */ + return (-1); } sr->smb_sid = od->d_sid; sr->sid_odir = od; - - return (-1); + return (0); } @@ -250,12 +249,10 @@ smb_rdir_next( dir->d_dir_snode, pc->dc_name, &fnode, &pc->dc_attr, 0, 0); if (rc != 0) { - if (rc != ENOENT) { + if (rc != ENOENT) return (rc); - } - else - continue; - /* NOTREACHED */ + + continue; } /* Root of file system? */ diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c index dff0a689dd..331c785202 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c @@ -56,16 +56,13 @@ extern int smb_maxbufsize; * be applied to its peer. */ -int smb_trans_ready(struct smb_xa *xa); -int smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa); -int smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa); -int smb_trans2_find(struct smb_request *sr, struct smb_xa *xa, int opcode); -int smb_trans2_query_fs_info(struct smb_request *sr, struct smb_xa *xa); +static int smb_trans_ready(struct smb_xa *); +static smb_sdrc_t smb_trans_dispatch(struct smb_request *, struct smb_xa *); +static smb_sdrc_t smb_trans2_dispatch(struct smb_request *, struct smb_xa *); +static smb_sdrc_t smb_nt_transact_query_quota(struct smb_request *, + struct smb_xa *); - -int smb_nt_transact_query_quota(struct smb_request *sr, struct smb_xa *xa); - -int +smb_sdrc_t smb_com_transaction(struct smb_request *sr) { int rc; @@ -81,16 +78,14 @@ smb_com_transaction(struct smb_request *sr) &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, msrcnt, suwcnt); if (xa == NULL) { smbsr_error(sr, 0, ERRSRV, ERRnoroom); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } /* Should be some alignment stuff here in SMB? */ @@ -101,8 +96,7 @@ smb_com_transaction(struct smb_request *sr) } if (rc != 0) { smb_xa_rele(sr->session, xa); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } xa->xa_smb_trans_name = MEM_STRDUP("smb", stn); @@ -115,17 +109,17 @@ smb_com_transaction(struct smb_request *sr) sr->smb_vwv.chain_offset, suwcnt * 2)) { smb_xa_rele(sr->session, xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { smb_xa_rele(sr->session, xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { smb_xa_rele(sr->session, xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } ready = smb_trans_ready(xa); @@ -133,26 +127,25 @@ smb_com_transaction(struct smb_request *sr) if (smb_xa_open(xa)) { smb_xa_rele(sr->session, xa); smbsr_error(sr, 0, ERRDOS, ERRsrverror); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->r_xa = xa; if (!ready) { - smbsr_encode_empty_result(sr); - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } if (!smb_xa_complete(xa)) { smb_xa_close(xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } return (smb_trans_dispatch(sr, xa)); } - -int +smb_sdrc_t smb_com_transaction_secondary(struct smb_request *sr) { uint16_t tpscnt, tdscnt, pscnt, psdisp; @@ -162,14 +155,14 @@ smb_com_transaction_secondary(struct smb_request *sr) if ((xa = smbsr_lookup_xa(sr)) == 0) { smbsr_error(sr, 0, ERRSRV, ERRsrverror); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } } @@ -180,10 +173,8 @@ smb_com_transaction_secondary(struct smb_request *sr) rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt, &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); mutex_enter(&xa->xa_mutex); xa->smb_tpscnt = tpscnt; /* might have shrunk */ @@ -195,13 +186,13 @@ smb_com_transaction_secondary(struct smb_request *sr) mutex_exit(&xa->xa_mutex); smb_xa_close(xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } mutex_exit(&xa->xa_mutex); @@ -214,8 +205,7 @@ smb_com_transaction_secondary(struct smb_request *sr) return (smb_trans_dispatch(sr, xa)); } - -int +smb_sdrc_t smb_com_ioctl(struct smb_request *sr) { uint16_t fid, category, function, tpscnt, tdscnt, mprcnt; @@ -227,23 +217,19 @@ smb_com_ioctl(struct smb_request *sr) &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt, &pdoff, &dscnt, &dsoff); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); return (SDRC_UNIMPLEMENTED); } - -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_ioctl_secondary(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); } - -int +smb_sdrc_t smb_com_transaction2(struct smb_request *sr) { unsigned char msrcnt, suwcnt; @@ -258,16 +244,14 @@ smb_com_transaction2(struct smb_request *sr) &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, msrcnt, suwcnt); if (xa == 0) { smbsr_error(sr, 0, ERRSRV, ERRnoroom); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } xa->smb_flags = flags; @@ -279,17 +263,17 @@ smb_com_transaction2(struct smb_request *sr) sr->smb_vwv.chain_offset, suwcnt*2)) { smb_xa_rele(sr->session, xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { smb_xa_rele(sr->session, xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { smb_xa_rele(sr->session, xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } ready = smb_trans_ready(xa); @@ -297,26 +281,25 @@ smb_com_transaction2(struct smb_request *sr) if (smb_xa_open(xa)) { smb_xa_rele(sr->session, xa); smbsr_error(sr, 0, ERRDOS, ERRsrverror); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->r_xa = xa; if (!ready) { - smbsr_encode_empty_result(sr); - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } if (!smb_xa_complete(xa)) { smb_xa_close(xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } return (smb_trans2_dispatch(sr, xa)); } - -int +smb_sdrc_t smb_com_transaction2_secondary(struct smb_request *sr) { uint16_t tpscnt, tdscnt, fid; @@ -326,14 +309,14 @@ smb_com_transaction2_secondary(struct smb_request *sr) if ((xa = smbsr_lookup_xa(sr)) == 0) { smbsr_error(sr, 0, ERRSRV, ERRsrverror); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } } @@ -344,10 +327,8 @@ smb_com_transaction2_secondary(struct smb_request *sr) rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); mutex_enter(&xa->xa_mutex); xa->smb_tpscnt = tpscnt; /* might have shrunk */ @@ -360,13 +341,13 @@ smb_com_transaction2_secondary(struct smb_request *sr) mutex_exit(&xa->xa_mutex); smb_xa_close(xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } mutex_exit(&xa->xa_mutex); @@ -379,7 +360,7 @@ smb_com_transaction2_secondary(struct smb_request *sr) return (smb_trans2_dispatch(sr, xa)); } -static int +static smb_sdrc_t smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) { int rc; @@ -419,15 +400,15 @@ smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) case NT_TRANSACT_QUERY_QUOTA: (void) smb_nt_transact_query_quota(sr, xa); smbsr_error(sr, 0, ERRSRV, ERRaccess); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); case NT_TRANSACT_SET_QUOTA: smbsr_error(sr, 0, ERRSRV, ERRaccess); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); default: smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } switch (rc) { @@ -442,7 +423,7 @@ smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) case SDRC_UNIMPLEMENTED: case SDRC_UNSUPPORTED: smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); default: break; @@ -456,7 +437,7 @@ smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) xa->smb_mprcnt < n_param || xa->smb_mdrcnt < n_data) { smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } /* neato, blast it over there */ @@ -468,7 +449,7 @@ smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) data_off = param_off + n_param + data_pad; /* Param off from hdr */ total_bytes = param_pad + n_param + data_pad + n_data; - smbsr_encode_result(sr, 18+n_setup, total_bytes, + rc = smbsr_encode_result(sr, 18+n_setup, total_bytes, "b 3. llllllllb C w #. C #. C", 18 + n_setup, /* wct */ n_param, /* Total Parameter Bytes */ @@ -486,35 +467,29 @@ smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) &xa->rep_param_mb, data_pad, &xa->rep_data_mb); - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } /* * smb_nt_transact_query_quota * - * Stub to help debunk this function. There are 16 parameter bytes. The - * first parameter is definitely the fid. The second looks like a flags - * field. Then there are 12 bytes (probably 3 dwords) - all zero. + * There are 16 parameter bytes: fid, flags and 12 zero bytes. */ -int +static smb_sdrc_t smb_nt_transact_query_quota(struct smb_request *sr, struct smb_xa *xa) { uint16_t fid; uint16_t flags; - int rc; - rc = smb_decode_mbc(&xa->req_param_mb, "%ww", sr, &fid, &flags); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smb_decode_mbc(&xa->req_param_mb, "%ww", sr, &fid, &flags)) + return (SDRC_ERROR_REPLY); return (SDRC_NORMAL_REPLY); } -int +smb_sdrc_t smb_com_nt_transact(struct smb_request *sr) { uint16_t Function; @@ -531,16 +506,14 @@ smb_com_nt_transact(struct smb_request *sr) &MaxDataCount, &pscnt, &psoff, &dscnt, &dsoff, &SetupCount, &Function); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount, MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount); if (xa == 0) { smbsr_error(sr, 0, ERRSRV, ERRnoroom); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } xa->smb_flags = 0; @@ -553,17 +526,17 @@ smb_com_nt_transact(struct smb_request *sr) sr->smb_vwv.chain_offset, SetupCount * 2)) { smb_xa_rele(sr->session, xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { smb_xa_rele(sr->session, xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { smb_xa_rele(sr->session, xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } ready = smb_trans_ready(xa); @@ -571,26 +544,26 @@ smb_com_nt_transact(struct smb_request *sr) if (smb_xa_open(xa)) { smb_xa_rele(sr->session, xa); smbsr_error(sr, 0, ERRDOS, ERRsrverror); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->r_xa = xa; if (!ready) { - smbsr_encode_empty_result(sr); - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } if (!smb_xa_complete(xa)) { smb_xa_close(xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } return (smb_nt_trans_dispatch(sr, xa)); } -int +smb_sdrc_t smb_com_nt_transact_secondary(struct smb_request *sr) { uint16_t tpscnt, tdscnt, fid; @@ -600,14 +573,14 @@ smb_com_nt_transact_secondary(struct smb_request *sr) if ((xa = smbsr_lookup_xa(sr)) == 0) { smbsr_error(sr, 0, ERRSRV, ERRsrverror); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } } @@ -618,10 +591,8 @@ smb_com_nt_transact_secondary(struct smb_request *sr) rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); mutex_enter(&xa->xa_mutex); xa->smb_tpscnt = tpscnt; /* might have shrunk */ @@ -634,13 +605,13 @@ smb_com_nt_transact_secondary(struct smb_request *sr) mutex_exit(&xa->xa_mutex); smb_xa_close(xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); smbsr_error(sr, 0, ERRDOS, ERRbadformat); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } mutex_exit(&xa->xa_mutex); @@ -653,7 +624,7 @@ smb_com_nt_transact_secondary(struct smb_request *sr) return (smb_nt_trans_dispatch(sr, xa)); } -int +static int smb_trans_ready(struct smb_xa *xa) { int rc; @@ -1221,7 +1192,9 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) /* Check buffer to have enough space */ if (shares_tot_byte == 0) { - return (SDRC_ERROR_REPLY); + (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", + ERROR_NOT_ENOUGH_MEMORY, 0, 0, 0); + return (SDRC_NORMAL_REPLY); } max_shares_per_packet = data_buf_limit / SHARE_INFO_1_SIZE; @@ -1526,8 +1499,7 @@ smb_trans_net_user_get_info(struct smb_request *sr, struct smb_xa *xa) return (SDRC_NORMAL_REPLY); } - -int +smb_sdrc_t smb_trans_server_get_info(struct smb_request *sr, struct smb_xa *xa) { uint16_t opcode, level, buf_size; @@ -1540,8 +1512,7 @@ smb_trans_server_get_info(struct smb_request *sr, struct smb_xa *xa) if (smb_decode_mbc(&xa->req_param_mb, "%wssww", sr, &opcode, &req_fmt, &rep_fmt, &level, &buf_size) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } comment = smb_info.si.skc_system_comment; @@ -1883,7 +1854,7 @@ is_supported_pipe(char *pname) return (1); } -int +static smb_sdrc_t smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) { int rc, pos; @@ -1928,7 +1899,7 @@ smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } rc = smb_decode_mbc(&xa->req_data_mb, "#B", @@ -1942,7 +1913,7 @@ smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) case TRANS_WAIT_NMPIPE: if (is_supported_pipe(xa->xa_smb_trans_name) == 0) { smbsr_error(sr, 0, ERRDOS, ERRbadfile); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } rc = SDRC_NORMAL_REPLY; break; @@ -2033,7 +2004,7 @@ smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) data_off = param_off + n_param + data_pad; total_bytes = param_pad + n_param + data_pad + n_data; - smbsr_encode_result(sr, 10+n_setup, total_bytes, + rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, "b ww 2. www www b . C w #. C #. C", 10 + n_setup, /* wct */ n_param, /* Total Parameter Bytes */ @@ -2051,7 +2022,7 @@ smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) &xa->rep_param_mb, data_pad, &xa->rep_data_mb); - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); trans_err_too_small: rc = NERR_BufTooSmall; @@ -2063,7 +2034,7 @@ trans_err_not_supported: trans_err: pos = MBC_LENGTH(&sr->reply) + 23; - smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww", + rc = smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww", 10, /* wct */ 4, 0, /* tpscnt tdscnt */ 4, pos, 0, /* pscnt psoff psdisp */ @@ -2072,11 +2043,10 @@ trans_err: 4, /* bcc */ rc, 0); /* converter word? */ - - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } -int +static smb_sdrc_t smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) { int rc, pos; @@ -2121,7 +2091,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) if (n_data == 0) { smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } rc = smb_com_trans2_find_first2(sr, xa); break; @@ -2134,7 +2104,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) if (n_data == 0) { smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } rc = smb_com_trans2_find_next2(sr, xa); break; @@ -2147,7 +2117,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) if (n_data == 0) { smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } rc = smb_com_trans2_query_fs_information(sr, xa); break; @@ -2160,7 +2130,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) if (n_data == 0) { smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } rc = smb_com_trans2_query_path_information(sr, xa); break; @@ -2173,7 +2143,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) if (n_data == 0) { smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } rc = smb_com_trans2_query_file_information(sr, xa); break; @@ -2246,7 +2216,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) total_bytes = param_pad + n_param + data_pad + n_data; - smbsr_encode_result(sr, 10+n_setup, total_bytes, + rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, fmt, 10 + n_setup, /* wct */ n_param, /* Total Parameter Bytes */ @@ -2264,7 +2234,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) &xa->rep_param_mb, nt_unknown_secret, &xa->rep_data_mb); - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); trans_err_too_small: rc = NERR_BufTooSmall; @@ -2276,7 +2246,7 @@ trans_err_not_supported: trans_err: pos = MBC_LENGTH(&sr->reply) + 23; - smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww", + rc = smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww", 10, /* wct */ 4, 0, /* tpscnt tdscnt */ 4, pos, 0, /* pscnt psoff psdisp */ @@ -2285,7 +2255,7 @@ trans_err: 4, /* bcc */ rc, 0); /* converter word? */ - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } smb_xa_t * diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_tree.c b/usr/src/uts/common/fs/smbsrv/smb_common_tree.c index 6947474f77..3c6232b61d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_tree.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_tree.c @@ -79,12 +79,12 @@ smbsr_connect_tree(struct smb_request *sr) */ if (sharename[1] != '\\') { smbsr_error(sr, 0, ERRSRV, ERRinvnetname); - /* NOTREACHED */ + return (ERRinvnetname); } if ((sharename = strchr(sharename+2, '\\')) == 0) { smbsr_error(sr, 0, ERRSRV, ERRinvnetname); - /* NOTREACHED */ + return (ERRinvnetname); } ++sharename; @@ -93,13 +93,13 @@ smbsr_connect_tree(struct smb_request *sr) * This should be a sharename: no embedded '\' allowed. */ smbsr_error(sr, 0, ERRSRV, ERRinvnetname); - /* NOTREACHED */ + return (ERRinvnetname); } if (smb_get_stype(sharename, sr->arg.tcon.service, &stype) != 0) { smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, ERRDOS, ERROR_BAD_DEV_TYPE); - /* NOTREACHED */ + return (ERROR_BAD_DEV_TYPE); } if ((rc = smbsr_setup_share(sr, sharename, stype, errmsg)) != 0) { @@ -112,7 +112,7 @@ smbsr_connect_tree(struct smb_request *sr) */ status = (rc == ERRaccess) ? NT_STATUS_ACCESS_DENIED : 0; smbsr_error(sr, status, ERRSRV, rc); - /* NOTREACHED */ + return (rc); } if (STYPE_ISDSK(sr->tid_tree->t_res_type)) { @@ -124,7 +124,7 @@ smbsr_connect_tree(struct smb_request *sr) smbsr_share_report(sr, sharename, access_msg, errmsg); } - return (rc); + return (0); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_copy.c b/usr/src/uts/common/fs/smbsrv/smb_copy.c index 4b33818eab..9d0d34a4f4 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_copy.c +++ b/usr/src/uts/common/fs/smbsrv/smb_copy.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -114,7 +114,7 @@ #include <smbsrv/smb_incl.h> /*ARGSUSED*/ -int +smb_sdrc_t smb_com_copy(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); diff --git a/usr/src/uts/common/fs/smbsrv/smb_create.c b/usr/src/uts/common/fs/smbsrv/smb_create.c index c38bbfd819..c8747bf925 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_create.c +++ b/usr/src/uts/common/fs/smbsrv/smb_create.c @@ -36,44 +36,27 @@ static uint32_t smb_common_create(struct smb_request *sr); * open the file and return a fid. The file is specified using a * fully qualified name relative to the tree. */ -int +smb_sdrc_t smb_com_create(struct smb_request *sr) { struct open_param *op = &sr->arg.open; - uint32_t status; bzero(op, sizeof (sr->arg.open)); - if (smbsr_decode_vwv(sr, "wl", &op->dattr, &op->utime.tv_sec) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "wl", &op->dattr, &op->utime.tv_sec) != 0) + return (SDRC_ERROR_REPLY); - if (smbsr_decode_data(sr, "%S", sr, &op->fqi.path) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_data(sr, "%S", sr, &op->fqi.path) != 0) + return (SDRC_ERROR_REPLY); op->create_disposition = FILE_OVERWRITE_IF; - status = smb_common_create(sr); - - switch (status) { - case NT_STATUS_SUCCESS: - break; - - case NT_STATUS_SHARING_VIOLATION: - smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, - ERRDOS, ERROR_SHARING_VIOLATION); - /* NOTREACHED */ - break; - - default: - smbsr_error(sr, status, 0, 0); - /* NOTREACHED */ - break; - } - smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0); + if (smb_common_create(sr) != NT_STATUS_SUCCESS) + return (SDRC_ERROR_REPLY); + + if (smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0)) + return (SDRC_ERROR_REPLY); + return (SDRC_NORMAL_REPLY); } @@ -81,44 +64,27 @@ smb_com_create(struct smb_request *sr) * Create a new file and return a fid. The file is specified using * a fully qualified name relative to the tree. */ -int +smb_sdrc_t smb_com_create_new(struct smb_request *sr) { struct open_param *op = &sr->arg.open; - uint32_t status; bzero(op, sizeof (sr->arg.open)); - if (smbsr_decode_vwv(sr, "wl", &op->dattr, &op->utime.tv_sec) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "wl", &op->dattr, &op->utime.tv_sec) != 0) + return (SDRC_ERROR_REPLY); - if (smbsr_decode_data(sr, "%S", sr, &op->fqi.path) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_data(sr, "%S", sr, &op->fqi.path) != 0) + return (SDRC_ERROR_REPLY); op->create_disposition = FILE_CREATE; - status = smb_common_create(sr); - - switch (status) { - case NT_STATUS_SUCCESS: - break; - - case NT_STATUS_SHARING_VIOLATION: - smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, - ERRDOS, ERROR_SHARING_VIOLATION); - /* NOTREACHED */ - break; - - default: - smbsr_error(sr, status, 0, 0); - /* NOTREACHED */ - break; - } - smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0); + if (smb_common_create(sr) != NT_STATUS_SUCCESS) + return (SDRC_ERROR_REPLY); + + if (smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0)) + return (SDRC_ERROR_REPLY); + return (SDRC_NORMAL_REPLY); } @@ -127,28 +93,23 @@ smb_com_create_new(struct smb_request *sr) * Create a unique file in the specified directory relative to the * current tree. No attributes are specified. */ -int +smb_sdrc_t smb_com_create_temporary(struct smb_request *sr) { static uint16_t tmp_id = 10000; struct open_param *op = &sr->arg.open; char name[SMB_CREATE_NAMEBUF_SZ]; char *buf; - uint32_t status; uint16_t reserved; uint16_t bcc; bzero(op, sizeof (sr->arg.open)); - if (smbsr_decode_vwv(sr, "wl", &reserved, &op->utime.tv_sec) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "wl", &reserved, &op->utime.tv_sec) != 0) + return (SDRC_ERROR_REPLY); - if (smbsr_decode_data(sr, "%S", sr, &op->fqi.path) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_data(sr, "%S", sr, &op->fqi.path) != 0) + return (SDRC_ERROR_REPLY); ++tmp_id; bcc = 1; /* null terminator */ @@ -158,25 +119,14 @@ smb_com_create_temporary(struct smb_request *sr) (void) snprintf(buf, MAXPATHLEN, "%s\\%s", op->fqi.path, name); op->fqi.path = buf; op->create_disposition = FILE_CREATE; - status = smb_common_create(sr); - - switch (status) { - case NT_STATUS_SUCCESS: - break; - - case NT_STATUS_SHARING_VIOLATION: - smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, - ERRDOS, ERROR_SHARING_VIOLATION); - /* NOTREACHED */ - break; - - default: - smbsr_error(sr, status, 0, 0); - /* NOTREACHED */ - break; - } - smbsr_encode_result(sr, 1, 0, "bwwbs", 1, sr->smb_fid, bcc, 4, name); + if (smb_common_create(sr) != NT_STATUS_SUCCESS) + return (SDRC_ERROR_REPLY); + + if (smbsr_encode_result(sr, 1, 0, "bwwbs", 1, sr->smb_fid, bcc, 4, + name)) + return (SDRC_ERROR_REPLY); + return (SDRC_NORMAL_REPLY); } @@ -200,7 +150,7 @@ smb_common_create(struct smb_request *sr) (op->share_access == ((uint32_t)SMB_INVALID_SHAREMODE))) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); - /* NOTREACHED */ + return (NT_STATUS_INVALID_PARAMETER); } op->dsize = 0; @@ -213,7 +163,7 @@ smb_common_create(struct smb_request *sr) } } - status = smb_open_subr(sr); + status = smb_common_open(sr); if (MYF_OPLOCK_TYPE(op->my_flags) == MYF_OPLOCK_NONE) { sr->smb_flg &= diff --git a/usr/src/uts/common/fs/smbsrv/smb_create_directory.c b/usr/src/uts/common/fs/smbsrv/smb_create_directory.c index cb6e3f6e72..797f585181 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_create_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_create_directory.c @@ -67,9 +67,6 @@ typedef struct { } SmbPath; -extern int smb_common_create_directory(struct smb_request *sr); - - static int smbpath_next(SmbPath* spp); static SmbPath* smbpath_new(SmbRequest* sr); @@ -80,21 +77,25 @@ static SmbPath* smbpath_new(SmbRequest* sr); * It is possible to get a full pathname here and the client expects any * or all of the components to be created if they don't already exist. */ -int +smb_sdrc_t smb_com_create_directory(struct smb_request *sr) { SmbPath* spp; DWORD status; int rc = 0; - if (smbsr_decode_data(sr, "%S", sr, &sr->arg.dirop.fqi.path) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ + if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERROR_ACCESS_DENIED); + return (SDRC_ERROR_REPLY); } + if (smbsr_decode_data(sr, "%S", sr, &sr->arg.dirop.fqi.path) != 0) + return (SDRC_ERROR_REPLY); + if ((status = smb_validate_dirname(sr->arg.dirop.fqi.path)) != 0) { smbsr_error(sr, status, ERRDOS, ERROR_INVALID_NAME); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } /* @@ -105,16 +106,20 @@ smb_com_create_directory(struct smb_request *sr) while (smbpath_next(spp)) { rc = smb_common_create_directory(sr); - if (rc != 0 && rc != EEXIST) + if (rc != 0 && rc != EEXIST) { smbsr_errno(sr, rc); + return (SDRC_ERROR_REPLY); + } } /* We should have created one directory successfully! */ - if (rc != 0) + if (rc != 0) { smbsr_errno(sr, rc); + return (SDRC_ERROR_REPLY); + } - smbsr_encode_empty_result(sr); - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } @@ -159,12 +164,6 @@ smb_common_create_directory(struct smb_request *sr) struct smb_node *dnode; struct smb_node *node; - if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_error(sr, NT_STATUS_ACCESS_DENIED, - ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ - } - sr->arg.dirop.fqi.srch_attr = 0; rc = smbd_fs_query(sr, &sr->arg.dirop.fqi, FQM_PATH_MUST_NOT_EXIST); diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete.c b/usr/src/uts/common/fs/smbsrv/smb_delete.c index c3a4dad862..94645c05d1 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_delete.c +++ b/usr/src/uts/common/fs/smbsrv/smb_delete.c @@ -86,7 +86,7 @@ static uint32_t smb_delete_check(smb_request_t *sr, smb_node_t *node, * ERRSRV/ERRinvid * ERRSRV/ERRbaduid */ -int +smb_sdrc_t smb_com_delete(struct smb_request *sr) { int rc; @@ -104,15 +104,14 @@ smb_com_delete(struct smb_request *sr) int is_stream; smb_odir_context_t *pc; - if (smbsr_decode_vwv(sr, "w", &sattr) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "w", &sattr) != 0) + return (SDRC_ERROR_REPLY); - if (smbsr_decode_data(sr, "%S", sr, &path) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_data(sr, "%S", sr, &path) != 0) + return (SDRC_ERROR_REPLY); + + if (smb_rdir_open(sr, path, sattr) != 0) + return (SDRC_ERROR_REPLY); pc = kmem_zalloc(sizeof (*pc), KM_SLEEP); fname = kmem_alloc(MAXNAMELEN, KM_SLEEP); @@ -121,8 +120,6 @@ smb_com_delete(struct smb_request *sr) fullname = kmem_alloc(MAXPATHLEN, KM_SLEEP); is_stream = smb_stream_parse_name(path, fname, sname); - - (void) smb_rdir_open(sr, path, sattr); dir_snode = sr->sid_odir->d_dir_snode; /* @@ -208,31 +205,15 @@ smb_com_delete(struct smb_request *sr) node = NULL; if (rc != 0) { - if (rc != ENOENT) { - smb_rdir_close(sr); - kmem_free(pc, sizeof (*pc)); - kmem_free(name, MAXNAMELEN); - kmem_free(fname, MAXNAMELEN); - kmem_free(sname, MAXNAMELEN); - kmem_free(fullname, MAXPATHLEN); - smbsr_errno(sr, rc); - /* NOTREACHED */ - } + if (rc != ENOENT) + goto delete_errno; } else { deleted++; } } if ((rc != 0) && (rc != ENOENT)) { - /* rc returned by smb_rdir_next() */ - smb_rdir_close(sr); - kmem_free(pc, sizeof (*pc)); - kmem_free(name, MAXNAMELEN); - kmem_free(fname, MAXNAMELEN); - kmem_free(sname, MAXNAMELEN); - kmem_free(fullname, MAXPATHLEN); - smbsr_errno(sr, rc); - /* NOTREACHED */ + goto delete_errno; } if (deleted == 0) { @@ -244,15 +225,24 @@ smb_com_delete(struct smb_request *sr) } smb_rdir_close(sr); + kmem_free(pc, sizeof (*pc)); + kmem_free(name, MAXNAMELEN); + kmem_free(fname, MAXNAMELEN); + kmem_free(sname, MAXNAMELEN); + kmem_free(fullname, MAXPATHLEN); - smbsr_encode_empty_result(sr); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); +delete_errno: + smb_rdir_close(sr); kmem_free(pc, sizeof (*pc)); kmem_free(name, MAXNAMELEN); kmem_free(fname, MAXNAMELEN); kmem_free(sname, MAXNAMELEN); kmem_free(fullname, MAXPATHLEN); - return (SDRC_NORMAL_REPLY); + smbsr_errno(sr, rc); + return (SDRC_ERROR_REPLY); delete_error: smb_rdir_close(sr); @@ -262,8 +252,7 @@ delete_error: kmem_free(sname, MAXNAMELEN); kmem_free(fullname, MAXPATHLEN); smbsr_error(sr, smberr.status, smberr.errcls, smberr.errcode); - /* NOTREACHED */ - return (SDRC_NORMAL_REPLY); /* compiler complains otherwise */ + return (SDRC_ERROR_REPLY); } uint32_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete_directory.c b/usr/src/uts/common/fs/smbsrv/smb_delete_directory.c index 514551ad97..75c31a35be 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_delete_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_delete_directory.c @@ -56,7 +56,7 @@ * UCHAR WordCount; Count of parameter words = 0 * USHORT ByteCount; Count of data bytes = 0 */ -int +smb_sdrc_t smb_com_delete_directory(struct smb_request *sr) { smb_node_t *dnode; @@ -65,20 +65,18 @@ smb_com_delete_directory(struct smb_request *sr) if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - if (smbsr_decode_data(sr, "%S", sr, &sr->arg.dirop.fqi.path) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_data(sr, "%S", sr, &sr->arg.dirop.fqi.path) != 0) + return (SDRC_ERROR_REPLY); sr->arg.dirop.fqi.srch_attr = 0; rc = smbd_fs_query(sr, &sr->arg.dirop.fqi, FQM_PATH_MUST_EXIST); if (rc) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } dnode = sr->arg.dirop.fqi.last_snode; @@ -90,7 +88,7 @@ smb_com_delete_directory(struct smb_request *sr) smbsr_error(sr, NT_STATUS_CANNOT_DELETE, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } smb_node_release(dnode); @@ -103,12 +101,12 @@ smb_com_delete_directory(struct smb_request *sr) smb_node_release(dnode); SMB_NULL_FQI_NODES(sr->arg.dirop.fqi); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } smb_node_release(dnode); SMB_NULL_FQI_NODES(sr->arg.dirop.fqi); - smbsr_encode_empty_result(sr); - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c index 0cc54ae43e..e62ddccaf6 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c +++ b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c @@ -149,87 +149,8 @@ static kstat_t *smb_dispatch_ksp = NULL; static kstat_named_t *smb_dispatch_kstat_data = NULL; static int smb_dispatch_kstat_size = 0; -static int is_andx_com(unsigned char); - -extern void smbsr_decode_error(struct smb_request *sr); -extern void smbsr_encode_error(struct smb_request *sr); -extern void smbsr_check_result(struct smb_request *sr, int wct, int bcc); - -extern int smb_com_cancel_forward(struct smb_request *); -extern int smb_com_check_directory(struct smb_request *); -extern int smb_com_close(struct smb_request *); -extern int smb_com_close_and_tree_disconnect(struct smb_request *); -extern int smb_com_close_print_file(struct smb_request *); -extern int smb_com_copy(struct smb_request *); -extern int smb_com_create(struct smb_request *); -extern int smb_com_create_directory(struct smb_request *); -extern int smb_com_create_new(struct smb_request *); -extern int smb_com_create_temporary(struct smb_request *); -extern int smb_com_delete(struct smb_request *); -extern int smb_com_delete_directory(struct smb_request *); -extern int smb_com_echo(struct smb_request *); -extern int smb_com_find(struct smb_request *); -extern int smb_com_find_close(struct smb_request *); -extern int smb_com_find_close2(struct smb_request *); -extern int smb_com_find_notify_close(struct smb_request *); -extern int smb_com_find_unique(struct smb_request *); -extern int smb_com_flush(struct smb_request *); -extern int smb_com_forward_user_name(struct smb_request *); -extern int smb_com_get_machine_name(struct smb_request *); -extern int smb_com_get_print_queue(struct smb_request *); -extern int smb_com_invalid_command(struct smb_request *); -extern int smb_com_ioctl(struct smb_request *); -extern int smb_com_ioctl_secondary(struct smb_request *); -extern int smb_com_lock_and_read(struct smb_request *); -extern int smb_com_lock_byte_range(struct smb_request *); -extern int smb_com_locking_andx(struct smb_request *); -extern int smb_com_logoff_andx(struct smb_request *); -extern int smb_com_move(struct smb_request *); -extern int smb_com_negotiate(struct smb_request *); -extern int smb_com_nt_cancel(struct smb_request *); -extern int smb_com_nt_create_andx(struct smb_request *); -extern int smb_com_nt_transact(struct smb_request *); -extern int smb_com_nt_transact_secondary(struct smb_request *); -extern int smb_com_open(struct smb_request *); -extern int smb_com_open_andx(struct smb_request *); -extern int smb_com_open_print_file(struct smb_request *); -extern int smb_com_process_exit(struct smb_request *); -extern int smb_com_query_information(struct smb_request *); -extern int smb_com_query_information2(struct smb_request *); -extern int smb_com_query_information_disk(struct smb_request *); -extern int smb_com_read(struct smb_request *); -extern int smb_com_read_andx(struct smb_request *); -extern int smb_com_read_mpx(struct smb_request *); -extern int smb_com_read_mpx_secondary(struct smb_request *); -extern int smb_com_read_raw(struct smb_request *); -extern int smb_com_rename(struct smb_request *); -extern int smb_com_search(struct smb_request *); -extern int smb_com_seek(struct smb_request *); -extern int smb_com_send_broadcast_message(struct smb_request *); -extern int smb_com_send_end_mb_message(struct smb_request *); -extern int smb_com_send_single_message(struct smb_request *); -extern int smb_com_send_start_mb_message(struct smb_request *); -extern int smb_com_send_text_mb_message(struct smb_request *); -extern int smb_com_session_setup_andx(struct smb_request *); -extern int smb_com_set_information(struct smb_request *); -extern int smb_com_set_information2(struct smb_request *); -extern int smb_com_transaction(struct smb_request *); -extern int smb_com_transaction2(struct smb_request *); -extern int smb_com_transaction2_secondary(struct smb_request *); -extern int smb_com_transaction_secondary(struct smb_request *); -extern int smb_com_tree_connect(struct smb_request *); -extern int smb_com_tree_connect_andx(struct smb_request *); -extern int smb_com_tree_disconnect(struct smb_request *); -extern int smb_com_unlock_byte_range(struct smb_request *); -extern int smb_com_write(struct smb_request *); -extern int smb_com_write_and_close(struct smb_request *); -extern int smb_com_write_and_unlock(struct smb_request *); -extern int smb_com_write_andx(struct smb_request *); -extern int smb_com_write_complete(struct smb_request *); -extern int smb_com_write_mpx(struct smb_request *); -extern int smb_com_write_mpx_secondary(struct smb_request *); -extern int smb_com_write_print_file(struct smb_request *); -extern int smb_com_write_raw(struct smb_request *); +static int is_andx_com(unsigned char); +static int smbsr_check_result(struct smb_request *, int, int); static smb_dispatch_table_t dispatch[256] = { { smb_com_create_directory, /* 0x00 000 */ @@ -715,8 +636,6 @@ static smb_dispatch_table_t dispatch[256] = { { 0, 0, 0, RW_READER, 0 } /* 0xFF 255 */ }; -int smb_watch = -1; -int smb_emit_sending = 0; /* * smbsr_cleanup @@ -767,12 +686,12 @@ smbsr_cleanup(struct smb_request *sr) mutex_exit(&sr->sr_mutex); } -int +void smb_dispatch_request(struct smb_request *sr) { - int rc; + smb_sdrc_t sdrc; smb_dispatch_table_t *sdd; - smb_error_t err; + boolean_t disconnect = B_FALSE; ASSERT(sr->tid_tree == 0); ASSERT(sr->uid_user == 0); @@ -799,15 +718,16 @@ smb_dispatch_request(struct smb_request *sr) &sr->smb_pid, &sr->smb_uid, &sr->smb_mid) != 0) { - return (-1); + disconnect = B_TRUE; + goto drop_connection; } /* - * The reply "header" is filled in now even though - * it most likely will be rewritten under reply_ready: - * below. Could just reserve the space. But this - * (for now) is convenient incase the dialect dispatcher - * has to send a special reply (like TRANSACT). + * The reply "header" is filled in now even though it will, + * most likely, be rewritten under reply_ready below. We + * could reserve the space but this is convenient in case + * the dialect dispatcher has to send a special reply (like + * TRANSACT). * * Ensure that the 32-bit error code flag is turned off. * Clients seem to set it in transact requests and they may @@ -839,14 +759,11 @@ smb_dispatch_request(struct smb_request *sr) */ if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { if (smb_sign_check_request(sr) != 0) { - err.severity = ERROR_SEVERITY_ERROR; - err.status = NT_STATUS_ACCESS_DENIED; - err.errcls = ERRDOS; - err.errcode = ERROR_ACCESS_DENIED; - smbsr_set_error(sr, &err); - rc = -1; + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERROR_ACCESS_DENIED); + disconnect = B_TRUE; smb_rwx_rwenter(&sr->session->s_lock, RW_READER); - goto reply_error; + goto report_error; } } @@ -856,17 +773,16 @@ andx_more: smb_rwx_rwenter(&sr->session->s_lock, sdd->sdt_slock_mode); if (smb_decode_mbc(&sr->command, "b", &sr->smb_wct) != 0) { - rc = -3; - goto cant_decode; + disconnect = B_TRUE; + goto report_error; } (void) MBC_SHADOW_CHAIN(&sr->smb_vwv, &sr->command, sr->command.chain_offset, sr->smb_wct * 2); - if (smb_decode_mbc(&sr->command, "#.w", - sr->smb_wct*2, &sr->smb_bcc) != 0) { - rc = -5; - goto cant_decode; + if (smb_decode_mbc(&sr->command, "#.w", sr->smb_wct*2, &sr->smb_bcc)) { + disconnect = B_TRUE; + goto report_error; } (void) MBC_SHADOW_CHAIN(&sr->smb_data, &sr->command, @@ -874,8 +790,8 @@ andx_more: sr->command.chain_offset += sr->smb_bcc; if (sr->command.chain_offset > sr->command.max_bytes) { - rc = -6; - goto cant_decode; + disconnect = B_TRUE; + goto report_error; } /* Store pointers for later */ @@ -885,8 +801,8 @@ andx_more: /* Peek ahead and don't disturb vwv */ if (smb_peek_mbc(&sr->smb_vwv, sr->smb_vwv.chain_offset, "b.w", &sr->andx_com, &sr->andx_off) < 0) { - rc = -7; - goto cant_decode; + disconnect = B_TRUE; + goto report_error; } } else { sr->andx_com = (unsigned char)-1; @@ -906,227 +822,178 @@ andx_more: } mutex_exit(&sr->sr_mutex); - if (sdd->sdt_function) { - - if ((rc = setjmp(&sr->exjb))) { - /* - * Handle any errors from raw write. - */ - if (sr->session->s_state == - SMB_SESSION_STATE_WRITE_RAW_ACTIVE) { - /* - * Set state so that the netbios session - * daemon will start accepting data again. - */ - sr->session->s_write_raw_status = 0; - sr->session->s_state = - SMB_SESSION_STATE_NEGOTIATED; - } - - /* - * We should never have sr->sr_keep set here - * since this is the error path. - */ - ASSERT(sr->sr_keep == 0); - - smbsr_cleanup(sr); + if (sdd->sdt_function == NULL) { + smbsr_error(sr, 0, ERRDOS, ERRbadfunc); + goto report_error; + } - if (sr->smb_com == smb_watch) { - smb_emit_sending = 1; - } - if (rc < 0) { - rc -= 1000; - goto cant_decode; - } - goto reply_error; + /* + * Setup UID and TID information (if required). Both functions + * will set the sr credentials. In domain mode, the user and + * tree credentials should be the same. In share mode, the + * tree credentials (defined in the share definition) should + * override the user credentials. + */ + if (!(sdd->sdt_flags & SDDF_SUPPRESS_UID)) { + sr->uid_user = smb_user_lookup_by_uid(sr->session, + &sr->user_cr, sr->smb_uid); + if (sr->uid_user == NULL) { + smbsr_error(sr, 0, ERRSRV, ERRbaduid); + goto report_error; } - /* - * Setup UID and TID information (if required). Both functions - * will set the sr credentials. In domain mode, the user and - * tree credentials should be the same. In share mode, the - * tree credentials (defined in the share definition) should - * override the user credentials. - */ - if (!(sdd->sdt_flags & SDDF_SUPPRESS_UID)) { - sr->uid_user = smb_user_lookup_by_uid(sr->session, - &sr->user_cr, sr->smb_uid); - if (sr->uid_user == NULL) { - smbsr_error(sr, 0, ERRSRV, ERRbaduid); - /* NOTREACHED */ - } - if (!(sdd->sdt_flags & SDDF_SUPPRESS_TID)) { - sr->tid_tree = smb_tree_lookup_by_tid( - sr->uid_user, sr->smb_tid); - if (sr->tid_tree == NULL) { - smbsr_error(sr, 0, ERRSRV, ERRinvnid); - /* NOTREACHED */ - } + if (!(sdd->sdt_flags & SDDF_SUPPRESS_TID)) { + sr->tid_tree = smb_tree_lookup_by_tid( + sr->uid_user, sr->smb_tid); + if (sr->tid_tree == NULL) { + smbsr_error(sr, 0, ERRSRV, ERRinvnid); + goto report_error; } } + } + /* + * If the command is not a read raw request we can set the + * state of the session back to SMB_SESSION_STATE_NEGOTIATED + * (if the current state is SMB_SESSION_STATE_OPLOCK_BREAKING). + * Otherwise we let the read raw handler to deal with it. + */ + if ((sr->session->s_state == SMB_SESSION_STATE_OPLOCK_BREAKING) && + (sr->smb_com != SMB_COM_READ_RAW)) { + krw_t mode; /* - * If the command is not a read raw request we can set the - * state of the session back to SMB_SESSION_STATE_NEGOTIATED - * (if the current state is SMB_SESSION_STATE_OPLOCK_BREAKING). - * Otherwise we let the read raw handler to deal with it. + * The lock may have to be upgraded because, at this + * point, we don't know how it was entered. We just + * know that it has to be entered in writer mode here. + * Whatever mode was used to enter the lock, it will + * be restored. */ - if ((sr->session->s_state == - SMB_SESSION_STATE_OPLOCK_BREAKING) && - (sr->smb_com != SMB_COM_READ_RAW)) { - krw_t mode; - /* - * The lock may have to be upgraded because, at this - * point, we don't know how it was entered. We just - * know that it has to be entered in writer mode here. - * Whatever mode was used to enter the lock, it will - * be restored. - */ - mode = smb_rwx_rwupgrade(&sr->session->s_lock); - if (sr->session->s_state == - SMB_SESSION_STATE_OPLOCK_BREAKING) { - sr->session->s_state = - SMB_SESSION_STATE_NEGOTIATED; - } - smb_rwx_rwdowngrade(&sr->session->s_lock, mode); - } + mode = smb_rwx_rwupgrade(&sr->session->s_lock); + if (sr->session->s_state == SMB_SESSION_STATE_OPLOCK_BREAKING) + sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; - DTRACE_PROBE1(smb__dispatch__com, struct smb_request_t *, sr); + smb_rwx_rwdowngrade(&sr->session->s_lock, mode); + } - /* - * Increment method invocation count. This value is exposed - * via kstats, and it represents a count of all the dispatched - * requests, including the ones that have a return value, other - * than SDRC_NORMAL_REPLY. - */ - SMB_ALL_DISPATCH_STAT_INCR(sdd->sdt_dispatch_stats.value.ui64); + DTRACE_PROBE1(smb__dispatch__com, struct smb_request_t *, sr); - rc = (*sdd->sdt_function)(sr); + /* + * Increment method invocation count. This value is exposed + * via kstats, and it represents a count of all the dispatched + * requests, including the ones that have a return value, other + * than SDRC_NORMAL_REPLY. + */ + SMB_ALL_DISPATCH_STAT_INCR(sdd->sdt_dispatch_stats.value.ui64); + if ((sdrc = (*sdd->sdt_function)(sr)) != SDRC_NORMAL_REPLY) { /* - * Only call smbsr_cleanup if smb->sr_keep is not set. The - * smb_nt_transact_notify_change function will set - * smb->sr_keep if it retains control of the request when - * it returns. In that case the notify change code - * will call smbsr_cleanup later when the request is finally - * completed. + * Handle errors from raw write. */ - if (sr->sr_keep == 0) - smbsr_cleanup(sr); - } else { - rc = SDRC_UNIMPLEMENTED; /* Unknown? */ + if (sr->session->s_state == + SMB_SESSION_STATE_WRITE_RAW_ACTIVE) { + /* + * Set state so that the netbios session + * daemon will start accepting data again. + */ + sr->session->s_write_raw_status = 0; + sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; + } } - if (rc != SDRC_NORMAL_REPLY) { /* normal case special & fast */ - switch (rc) { - case SDRC_NORMAL_REPLY: - break; + /* + * Only call smbsr_cleanup if smb->sr_keep is not set. + * smb_nt_transact_notify_change will set smb->sr_keep if it + * retains control of the request when it returns. In that + * case the notify change code will call smbsr_cleanup later + * when the request has completed. + */ + if (sr->sr_keep == 0) + smbsr_cleanup(sr); - case SDRC_ERROR_REPLY: - goto reply_error; - - case SDRC_DROP_VC: - switch (sr->session->s_state) { - case SMB_SESSION_STATE_DISCONNECTED: - case SMB_SESSION_STATE_TERMINATED: - break; - default: - smb_soshutdown(sr->session->sock); - break; - } - goto reply_error; + switch (sdrc) { + case SDRC_NORMAL_REPLY: + break; - case SDRC_NO_REPLY: - /* tricky. */ - smb_rwx_rwexit(&sr->session->s_lock); - return (0); + case SDRC_DROP_VC: + disconnect = B_TRUE; + goto drop_connection; - case SDRC_UNIMPLEMENTED: - sr->smb_rcls = ERRDOS; - sr->smb_err = ERRbadfunc; - goto reply_error; + case SDRC_NO_REPLY: + smb_rwx_rwexit(&sr->session->s_lock); + return; - default: - sr->smb_rcls = ERRDOS; - sr->smb_err = ERRerror; /* need better */ - goto reply_error; - } + case SDRC_ERROR_REPLY: + goto report_error; + + case SDRC_UNIMPLEMENTED: + case SDRC_UNSUPPORTED: + default: + smbsr_error(sr, 0, ERRDOS, ERRbadfunc); + goto report_error; } + /* + * If there's no AndX command, we're done. + */ if (sr->andx_com == 0xff) goto reply_ready; - /* have to back-patch the AndXCommand and AndXOffset */ + /* + * Otherwise, we have to back-patch the AndXCommand and AndXOffset + * and continue processing. + */ sr->andx_prev_wct = sr->cur_reply_offset; (void) smb_poke_mbc(&sr->reply, sr->andx_prev_wct + 1, "b.w", sr->andx_com, MBC_LENGTH(&sr->reply)); smb_rwx_rwexit(&sr->session->s_lock); - /* now it gets interesting */ sr->command.chain_offset = sr->orig_request_hdr + sr->andx_off; - sr->smb_com = sr->andx_com; - goto andx_more; -reply_ready: - - if (SMB_TREE_CASE_INSENSITIVE(sr)) { - sr->smb_flg |= SMB_FLAGS_CASE_INSENSITIVE; - } else { - sr->smb_flg &= ~SMB_FLAGS_CASE_INSENSITIVE; - } - - (void) smb_poke_mbc(&sr->reply, 0, SMB_HEADER_ED_FMT, - sr->first_smb_com, - sr->smb_rcls, - sr->smb_reh, - sr->smb_err, - sr->smb_flg | SMB_FLAGS_REPLY, - sr->smb_flg2, - sr->smb_pid_high, - sr->smb_sig, - sr->smb_tid, - sr->smb_pid, - sr->smb_uid, - sr->smb_mid); - - if (sr->session->signing.flags & SMB_SIGNING_ENABLED) - smb_sign_reply(sr, NULL); - - if ((rc = smb_session_send(sr->session, 0, &sr->reply)) == 0) - sr->reply.chain = 0; - - smb_rwx_rwexit(&sr->session->s_lock); - - return (rc); - -cant_decode: -reply_error: +report_error: sr->reply.chain_offset = sr->cur_reply_offset; (void) smb_encode_mbc(&sr->reply, "bw", 0, 0); sr->smb_wct = 0; sr->smb_bcc = 0; - if (sr->smb_rcls == 0) { - sr->smb_rcls = ERRSRV; - sr->smb_err = ERRerror; + if (sr->smb_rcls == 0) + smbsr_error(sr, 0, ERRSRV, ERRerror); + +reply_ready: + smbsr_send_reply(sr); + +drop_connection: + if (disconnect) { + switch (sr->session->s_state) { + case SMB_SESSION_STATE_DISCONNECTED: + case SMB_SESSION_STATE_TERMINATED: + break; + default: + smb_soshutdown(sr->session->sock); + sr->session->s_state = SMB_SESSION_STATE_DISCONNECTED; + break; + } } - goto reply_ready; + + smb_rwx_rwexit(&sr->session->s_lock); } +int +smbsr_encode_empty_result(struct smb_request *sr) +{ + return (smbsr_encode_result(sr, 0, 0, "bw", 0, 0)); +} -void -smbsr_encode_result(struct smb_request *sr, int wct, - int bcc, char *fmt, ...) +int +smbsr_encode_result(struct smb_request *sr, int wct, int bcc, char *fmt, ...) { va_list ap; - if (MBC_LENGTH(&sr->reply) != sr->cur_reply_offset) { - smbsr_encode_error(sr); - } + if (MBC_LENGTH(&sr->reply) != sr->cur_reply_offset) + return (-1); va_start(ap, fmt); (void) smb_mbc_encode(&sr->reply, fmt, ap); @@ -1135,10 +1002,13 @@ smbsr_encode_result(struct smb_request *sr, int wct, sr->smb_wct = (unsigned char)wct; sr->smb_bcc = (uint16_t)bcc; - smbsr_check_result(sr, wct, bcc); + if (smbsr_check_result(sr, wct, bcc) != 0) + return (-1); + + return (0); } -void +static int smbsr_check_result(struct smb_request *sr, int wct, int bcc) { int offset = sr->cur_reply_offset; @@ -1153,53 +1023,44 @@ smbsr_check_result(struct smb_request *sr, int wct, int bcc) m = m->m_next; } - if ((offset + 3) > total_bytes) { - smbsr_encode_error(sr); - /* NOTREACHED */ - } + if ((offset + 3) > total_bytes) + return (-1); (void) smb_peek_mbc(&sr->reply, offset, "b", &temp); - if (temp != wct) { - smbsr_encode_error(sr); - /* NOTREACHED */ - } + if (temp != wct) + return (-1); - if ((offset + (wct * 2 + 1)) > total_bytes) { - smbsr_encode_error(sr); - /* NOTREACHED */ - } + if ((offset + (wct * 2 + 1)) > total_bytes) + return (-1); /* reply wct & vwv seem ok, consider data now */ offset += wct * 2 + 1; - if ((offset + 2) > total_bytes) { - smbsr_encode_error(sr); - } + if ((offset + 2) > total_bytes) + return (-1); (void) smb_peek_mbc(&sr->reply, offset, "bb", &temp, &temp1); if (bcc == VAR_BCC) { if ((temp != 0xFF) || (temp1 != 0xFF)) { - smbsr_encode_error(sr); - /* NOTREACHED */ + return (-1); } else { bcc = (total_bytes - offset) - 2; (void) smb_poke_mbc(&sr->reply, offset, "bb", bcc, bcc >> 8); } } else { - if ((temp != (bcc&0xFF)) || (temp1 != ((bcc>>8)&0xFF))) { - smbsr_encode_error(sr); - } + if ((temp != (bcc&0xFF)) || (temp1 != ((bcc>>8)&0xFF))) + return (-1); } offset += bcc + 2; - if (offset != total_bytes) { - smbsr_encode_error(sr); - } + if (offset != total_bytes) + return (-1); sr->smb_wct = (unsigned char)wct; sr->smb_bcc = (uint16_t)bcc; + return (0); } int @@ -1229,6 +1090,11 @@ smbsr_decode_data(struct smb_request *sr, char *fmt, ...) void smbsr_send_reply(struct smb_request *sr) { + if (SMB_TREE_CASE_INSENSITIVE(sr)) + sr->smb_flg |= SMB_FLAGS_CASE_INSENSITIVE; + else + sr->smb_flg &= ~SMB_FLAGS_CASE_INSENSITIVE; + (void) smb_poke_mbc(&sr->reply, 0, SMB_HEADER_ED_FMT, sr->first_smb_com, sr->smb_rcls, @@ -1246,26 +1112,8 @@ smbsr_send_reply(struct smb_request *sr) if (sr->session->signing.flags & SMB_SIGNING_ENABLED) smb_sign_reply(sr, NULL); - (void) smb_session_send(sr->session, 0, &sr->reply); -} - - -void -smbsr_decode_error(struct smb_request *sr) -{ - longjmp(&sr->exjb); -} - -void -smbsr_encode_error(struct smb_request *sr) -{ - longjmp(&sr->exjb); -} - -void -smbsr_encode_empty_result(struct smb_request *sr) -{ - smbsr_encode_result(sr, 0, 0, "bw", 0, 0); + if (smb_session_send(sr->session, 0, &sr->reply) == 0) + sr->reply.chain = 0; } /* @@ -1330,12 +1178,8 @@ smbsr_map_errno(int errnum, smb_error_t *err) void smbsr_errno(struct smb_request *sr, int errnum) { - smb_error_t err; - - smbsr_map_errno(errnum, &err); - smbsr_set_error(sr, &err); - longjmp(&sr->exjb); - /* NOTREACHED */ + smbsr_map_errno(errnum, &sr->smb_error); + smbsr_set_error(sr, &sr->smb_error); } /* @@ -1344,14 +1188,12 @@ smbsr_errno(struct smb_request *sr, int errnum) void smbsr_warn(smb_request_t *sr, DWORD status, uint16_t errcls, uint16_t errcode) { - smb_error_t err; - - err.severity = ERROR_SEVERITY_WARNING; - err.status = status; - err.errcls = errcls; - err.errcode = errcode; + sr->smb_error.severity = ERROR_SEVERITY_WARNING; + sr->smb_error.status = status; + sr->smb_error.errcls = errcls; + sr->smb_error.errcode = errcode; - smbsr_set_error(sr, &err); + smbsr_set_error(sr, &sr->smb_error); } /* @@ -1360,16 +1202,12 @@ smbsr_warn(smb_request_t *sr, DWORD status, uint16_t errcls, uint16_t errcode) void smbsr_error(smb_request_t *sr, DWORD status, uint16_t errcls, uint16_t errcode) { - smb_error_t err; + sr->smb_error.severity = ERROR_SEVERITY_ERROR; + sr->smb_error.status = status; + sr->smb_error.errcls = errcls; + sr->smb_error.errcode = errcode; - err.severity = ERROR_SEVERITY_ERROR; - err.status = status; - err.errcls = errcls; - err.errcode = errcode; - - smbsr_set_error(sr, &err); - longjmp(&sr->exjb); - /* NOTREACHED */ + smbsr_set_error(sr, &sr->smb_error); } /* @@ -1466,7 +1304,7 @@ is_andx_com(unsigned char com) * Invalid command stub. */ /*ARGSUSED*/ -int +smb_sdrc_t smb_com_invalid_command(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); diff --git a/usr/src/uts/common/fs/smbsrv/smb_echo.c b/usr/src/uts/common/fs/smbsrv/smb_echo.c index 8a386c9959..becab9b87e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_echo.c +++ b/usr/src/uts/common/fs/smbsrv/smb_echo.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,7 +36,7 @@ * Each response echoes the data sent, though ByteCount may indicate * no data. If echo-count is zero, no response is sent. */ -int +smb_sdrc_t smb_com_echo(struct smb_request *sr) { unsigned short necho; @@ -45,19 +45,16 @@ smb_com_echo(struct smb_request *sr) struct mbuf_chain reply; char *data; - if (smbsr_decode_vwv(sr, "w", &necho) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "w", &necho) != 0) + return (SDRC_ERROR_REPLY); nbytes = sr->smb_bcc; - data = smbsr_malloc(&sr->request_storage, nbytes); - (void) smb_decode_mbc(&sr->smb_data, "#c", nbytes, data); + if (smb_decode_mbc(&sr->smb_data, "#c", nbytes, data)) + return (SDRC_ERROR_REPLY); for (i = 1; i <= necho; ++i) { - MBC_INIT(&reply, SMB_HEADER_ED_LEN + 10 + nbytes); (void) smb_encode_mbc(&reply, SMB_HEADER_ED_FMT, @@ -89,7 +86,7 @@ smb_com_echo(struct smb_request *sr) /* * Broadcast messages are not supported. */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_send_broadcast_message(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); @@ -98,7 +95,7 @@ smb_com_send_broadcast_message(struct smb_request *sr) /* * Multi-block messages are not supported. */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_send_end_mb_message(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); @@ -107,7 +104,7 @@ smb_com_send_end_mb_message(struct smb_request *sr) /* * Single-block messages are not supported. */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_send_single_message(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); @@ -116,7 +113,7 @@ smb_com_send_single_message(struct smb_request *sr) /* * Multi-block messages are not supported. */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_send_start_mb_message(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); @@ -125,7 +122,7 @@ smb_com_send_start_mb_message(struct smb_request *sr) /* * Multi-block messages are not supported. */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_send_text_mb_message(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); diff --git a/usr/src/uts/common/fs/smbsrv/smb_find.c b/usr/src/uts/common/fs/smbsrv/smb_find.c index a45e5cab64..eac82b3349 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_find.c +++ b/usr/src/uts/common/fs/smbsrv/smb_find.c @@ -209,7 +209,7 @@ * ERRSRV/ERRaccess * ERRSRV/ERRinvnid */ -int +smb_sdrc_t smb_com_find(struct smb_request *sr) { int rc; @@ -222,27 +222,23 @@ smb_com_find(struct smb_request *sr) unsigned short key_len; smb_odir_context_t *pc; - if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) + return (SDRC_ERROR_REPLY); - if ((smbsr_decode_data(sr, "%Abw", sr, &path, &type, &key_len) != 0) || - (type != 0x05)) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + rc = smbsr_decode_data(sr, "%Abw", sr, &path, &type, &key_len); + if ((rc != 0) || (type != 0x05)) + return (SDRC_ERROR_REPLY); if (key_len == 0) { /* begin search */ - (void) smb_rdir_open(sr, path, sattr); + if (smb_rdir_open(sr, path, sattr) != 0) + return (SDRC_ERROR_REPLY); cookie = 0; } else if (key_len == 21) { sr->smb_sid = 0; if (smb_decode_mbc(&sr->smb_data, SMB_RESUME_KEY_FMT, filename, &sr->smb_sid, &cookie) != 0) { /* We don't know which rdir to close */ - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, @@ -250,14 +246,13 @@ smb_com_find(struct smb_request *sr) if (sr->sid_odir == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } cookie--; /* +1 when returned */ } else { /* We don't know which rdir to close */ - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } (void) smb_encode_mbc(&sr->reply, "bwwbw", 1, 0, VAR_BCC, 5, 0); @@ -287,21 +282,20 @@ smb_com_find(struct smb_request *sr) /* returned error by smb_rdir_next() */ smb_rdir_close(sr); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (count == 0) { smb_rdir_close(sr); smbsr_error(sr, 0, ERRDOS, ERRnofiles); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } rc = (MBC_LENGTH(&sr->reply) - sr->cur_reply_offset) - 8; - if (smb_poke_mbc(&sr->reply, sr->cur_reply_offset, - "bwwbw", 1, count, rc+3, 5, rc) < 0) { + if (smb_poke_mbc(&sr->reply, sr->cur_reply_offset, "bwwbw", + 1, count, rc+3, 5, rc) < 0) { smb_rdir_close(sr); - smbsr_encode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } return (SDRC_NORMAL_REPLY); @@ -385,7 +379,7 @@ smb_com_find(struct smb_request *sr) * ERRSRV/ERRerror * ERRSRV/ERRinvnid */ -int +smb_sdrc_t smb_com_find_close(struct smb_request *sr) { unsigned short sattr, maxcount; @@ -396,28 +390,23 @@ smb_com_find_close(struct smb_request *sr) unsigned short key_len; int rc; - if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) + return (SDRC_ERROR_REPLY); rc = smbsr_decode_data(sr, "%Abw", sr, &path, &type, &key_len); - if ((rc != 0) || (type != 0x05)) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if ((rc != 0) || (type != 0x05)) + return (SDRC_ERROR_REPLY); if (key_len == 0) { /* begin search */ smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (key_len == 21) { sr->smb_sid = 0; if (smb_decode_mbc(&sr->smb_data, SMB_RESUME_KEY_FMT, filename, &sr->smb_sid, &cookie) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, @@ -425,16 +414,16 @@ smb_com_find_close(struct smb_request *sr) if (sr->sid_odir == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } cookie--; /* +1 when returned */ } else { - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } smb_rdir_close(sr); - smbsr_encode_result(sr, 1, 3, "bwwbw", 1, 0, 3, 5, 0); + if (smbsr_encode_result(sr, 1, 3, "bwwbw", 1, 0, 3, 5, 0)) + return (SDRC_ERROR_REPLY); return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_find_notify_close.c b/usr/src/uts/common/fs/smbsrv/smb_find_notify_close.c index 46a9953b55..0c3c4a6462 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_find_notify_close.c +++ b/usr/src/uts/common/fs/smbsrv/smb_find_notify_close.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -71,7 +71,7 @@ * As far as I can tell, this part of the protocol is not implemented * by NT server. */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_find_notify_close(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); diff --git a/usr/src/uts/common/fs/smbsrv/smb_find_unique.c b/usr/src/uts/common/fs/smbsrv/smb_find_unique.c index f9686297f0..adb3e93dd6 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_find_unique.c +++ b/usr/src/uts/common/fs/smbsrv/smb_find_unique.c @@ -204,7 +204,7 @@ * ERRSRV/ERRaccess * ERRSRV/ERRinvnid */ -int +smb_sdrc_t smb_com_find_unique(struct smb_request *sr) { int rc; @@ -217,26 +217,26 @@ smb_com_find_unique(struct smb_request *sr) vdb = kmem_alloc(sizeof (struct vardata_block), KM_SLEEP); if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) { kmem_free(vdb, sizeof (struct vardata_block)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (smbsr_decode_data(sr, "%AV", sr, &path, vdb) != 0) { kmem_free(vdb, sizeof (struct vardata_block)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (vdb->len != 0) { kmem_free(vdb, sizeof (struct vardata_block)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } (void) smb_encode_mbc(&sr->reply, "bwwbw", 1, 0, VAR_BCC, 5, 0); /* begin search */ - (void) smb_rdir_open(sr, path, sattr); + if (smb_rdir_open(sr, path, sattr) != 0) { + kmem_free(vdb, sizeof (struct vardata_block)); + return (SDRC_ERROR_REPLY); + } pc = kmem_zalloc(sizeof (*pc), KM_SLEEP); pc->dc_cookie = 0; @@ -265,21 +265,20 @@ smb_com_find_unique(struct smb_request *sr) /* returned error by smb_rdir_next() */ kmem_free(vdb, sizeof (struct vardata_block)); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (count == 0) { kmem_free(vdb, sizeof (struct vardata_block)); smbsr_error(sr, 0, ERRDOS, ERRnofiles); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } rc = (MBC_LENGTH(&sr->reply) - sr->cur_reply_offset) - 8; if (smb_poke_mbc(&sr->reply, sr->cur_reply_offset, "bwwbw", 1, count, rc+3, 5, rc) < 0) { kmem_free(vdb, sizeof (struct vardata_block)); - smbsr_encode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } kmem_free(vdb, sizeof (struct vardata_block)); return (SDRC_NORMAL_REPLY); diff --git a/usr/src/uts/common/fs/smbsrv/smb_flush.c b/usr/src/uts/common/fs/smbsrv/smb_flush.c index c3da4a2352..303c0d5335 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_flush.c +++ b/usr/src/uts/common/fs/smbsrv/smb_flush.c @@ -73,20 +73,19 @@ smb_commit_required(int state) * We need to protect the list because there's a good chance we'll * block during the flush operation. */ -int +smb_sdrc_t smb_com_flush(smb_request_t *sr) { smb_ofile_t *file; smb_llist_t *flist; + int rc; - if (smbsr_decode_vwv(sr, "w", &sr->smb_fid) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "w", &sr->smb_fid) != 0) + return (SDRC_ERROR_REPLY); if (smb_flush_required == 0) { - smbsr_encode_empty_result(sr); - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } if (sr->smb_fid != 0xffff) { @@ -95,7 +94,7 @@ smb_com_flush(smb_request_t *sr) if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } smb_flush_file(sr, sr->fid_ofile); @@ -111,8 +110,9 @@ smb_com_flush(smb_request_t *sr) } smb_llist_exit(flist); } - smbsr_encode_empty_result(sr); - return (SDRC_NORMAL_REPLY); + + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } @@ -122,7 +122,8 @@ smb_com_flush(smb_request_t *sr) * If writes on this file are not synchronous, flush it using the NFSv3 * commit interface. */ -static void smb_flush_file(struct smb_request *sr, struct smb_ofile *ofile) +static void +smb_flush_file(struct smb_request *sr, struct smb_ofile *ofile) { if ((ofile->f_node->flags & NODE_FLAGS_WRITE_THROUGH) == 0) (void) smb_fsop_commit(sr, sr->user_cr, ofile->f_node); diff --git a/usr/src/uts/common/fs/smbsrv/smb_forward.c b/usr/src/uts/common/fs/smbsrv/smb_forward.c index 498e3bcaa7..d97b3a7097 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_forward.c +++ b/usr/src/uts/common/fs/smbsrv/smb_forward.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -69,7 +69,7 @@ * ERRSRV/<implementation specific> * ERRHRD/<implementation specific> */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_forward_user_name(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); @@ -105,7 +105,7 @@ smb_com_forward_user_name(struct smb_request *sr) * ERRSRV/<implementation specific> * ERRHRD/<implementation specific> */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_cancel_forward(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); @@ -141,7 +141,7 @@ smb_com_cancel_forward(struct smb_request *sr) * ERRSRV/ERRinvnid * ERRSRV/<implementation specific> */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_get_machine_name(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c index 3c2349a482..26774a1516 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c +++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c @@ -299,6 +299,7 @@ smb_fsop_create( smb_attr_t *ret_attr) { struct open_param *op = &sr->arg.open; + boolean_t no_xvattr = B_FALSE; smb_node_t *fnode; smb_attr_t file_attr; vnode_t *xattrdirvp; @@ -404,6 +405,31 @@ smb_fsop_create( return (rc); } + if (sr && sr->tid_tree) + if (sr->tid_tree->t_flags & SMB_TREE_FLAG_UFS) + no_xvattr = B_TRUE; + + attr->sa_vattr.va_uid = file_attr.sa_vattr.va_uid; + attr->sa_vattr.va_gid = file_attr.sa_vattr.va_gid; + attr->sa_mask = SMB_AT_UID | SMB_AT_GID; + + /* + * The second parameter of smb_vop_setattr() is set to + * NULL, even though an unnamed stream exists. This is + * because we want to set the UID and GID on the named + * stream in this case for consistency with the (unnamed + * stream) file (see comments for smb_vop_setattr()). + */ + + rc = smb_vop_setattr(vp, NULL, attr, 0, kcred, no_xvattr); + + if (rc != 0) { + smb_node_release(fnode); + kmem_free(fname, MAXNAMELEN); + kmem_free(sname, MAXNAMELEN); + return (rc); + } + *ret_snode = smb_stream_node_lookup(sr, cr, fnode, xattrdirvp, vp, sname, ret_attr); diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c index d9773cb50f..c626add082 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c +++ b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c @@ -62,23 +62,22 @@ #include <smbsrv/smb_incl.h> -int +smb_sdrc_t smb_com_lock_byte_range(struct smb_request *sr) { uint32_t count; uint32_t off; DWORD result; + int rc; - if (smbsr_decode_vwv(sr, "wll", &sr->smb_fid, &count, &off) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "wll", &sr->smb_fid, &count, &off) != 0) + return (SDRC_ERROR_REPLY); sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } /* @@ -91,10 +90,9 @@ smb_com_lock_byte_range(struct smb_request *sr) (u_offset_t)off, (uint64_t)count, 0, SMB_LOCK_TYPE_READWRITE); if (result != NT_STATUS_SUCCESS) { smb_lock_range_error(sr, result); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } - smbsr_encode_empty_result(sr); - - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c index b39188ebbd..928f124338 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c +++ b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c @@ -691,7 +691,6 @@ smb_lock_range_error(smb_request_t *sr, uint32_t status32) errcode = ERRlock; smbsr_error(sr, status32, ERRDOS, errcode); - /* NOTREACHED */ } /* diff --git a/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c b/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c index 4aa585091e..9365ff143e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c @@ -213,7 +213,7 @@ #include <smbsrv/smb_incl.h> -int +smb_sdrc_t smb_com_locking_andx(struct smb_request *sr) { unsigned short i; @@ -232,15 +232,13 @@ smb_com_locking_andx(struct smb_request *sr) rc = smbsr_decode_vwv(sr, "4.wbblww", &sr->smb_fid, &lock_type, &oplock_level, &timeout, &unlock_num, &lock_num); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (lock_type & LOCKING_ANDX_SHARED_LOCK) @@ -275,7 +273,7 @@ smb_com_locking_andx(struct smb_request *sr) */ if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) { smbsr_error(sr, 0, ERRDOS, ERRnoatomiclocks); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } /* @@ -284,7 +282,7 @@ smb_com_locking_andx(struct smb_request *sr) if (lock_type & LOCKING_ANDX_CANCEL_LOCK) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } if (lock_type & LOCKING_ANDX_LARGE_FILES) { @@ -294,7 +292,7 @@ smb_com_locking_andx(struct smb_request *sr) if (sr->session->dialect < NT_LM_0_12) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } for (i = 0; i < unlock_num; i++) { @@ -306,7 +304,7 @@ smb_com_locking_andx(struct smb_request *sr) * even when STATUS32 has been negotiated. */ smbsr_error(sr, 0, ERRSRV, ERRerror); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } result = smb_unlock_range(sr, sr->fid_ofile->f_node, @@ -314,7 +312,7 @@ smb_com_locking_andx(struct smb_request *sr) if (result != NT_STATUS_SUCCESS) { smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, ERRDOS, ERRnotlocked); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } } @@ -323,14 +321,14 @@ smb_com_locking_andx(struct smb_request *sr) &sr->smb_pid, &offset64, &length64); if (rc) { smbsr_error(sr, 0, ERRSRV, ERRerror); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } result = smb_lock_range(sr, sr->fid_ofile, offset64, length64, timeout, ltype); if (result != NT_STATUS_SUCCESS) { smb_lock_range_error(sr, result); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } } } else { @@ -339,7 +337,7 @@ smb_com_locking_andx(struct smb_request *sr) &offset32, &length32); if (rc) { smbsr_error(sr, 0, ERRSRV, ERRerror); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } result = smb_unlock_range(sr, sr->fid_ofile->f_node, @@ -347,7 +345,7 @@ smb_com_locking_andx(struct smb_request *sr) if (result != NT_STATUS_SUCCESS) { smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, ERRDOS, ERRnotlocked); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } } @@ -356,7 +354,7 @@ smb_com_locking_andx(struct smb_request *sr) &offset32, &length32); if (rc) { smbsr_error(sr, 0, ERRSRV, ERRerror); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } result = smb_lock_range(sr, sr->fid_ofile, @@ -365,13 +363,13 @@ smb_com_locking_andx(struct smb_request *sr) timeout, ltype); if (result != NT_STATUS_SUCCESS) { smb_lock_range_error(sr, result); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } } } sr->smb_pid = pid; - smbsr_encode_result(sr, 2, 0, "bb.ww", 2, sr->andx_com, 7, 0); - + if (smbsr_encode_result(sr, 2, 0, "bb.ww", 2, sr->andx_com, 7, 0)) + return (SDRC_ERROR_REPLY); return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c b/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c index 4b56c61b73..446e2d4b37 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c @@ -62,16 +62,17 @@ * ERRSRV/invnid - TID was invalid * ERRSRV/baduid - UID was invalid */ -int +smb_sdrc_t smb_com_logoff_andx(struct smb_request *sr) { if (sr->uid_user == NULL) { smbsr_error(sr, 0, ERRSRV, ERRbaduid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } smb_user_logoff(sr->uid_user); - smbsr_encode_result(sr, 2, 0, "bb.ww", 2, sr->andx_com, -1, 0); + if (smbsr_encode_result(sr, 2, 0, "bb.ww", 2, sr->andx_com, -1, 0)) + return (SDRC_ERROR_REPLY); return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c b/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c index d97f410e8b..435e81d842 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c +++ b/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1599,36 +1599,6 @@ smb_decode_vwv(struct smb_request *sr, char *fmt, ...) int -smb_decode_data(struct smb_request *sr, char *fmt, ...) -{ - if (smb_decode_mbc(&sr->smb_data, fmt, (int *)(&fmt + 1)) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } - return (0); -} - - -void -smb_encode_header(struct smb_request *sr, int wct, - int bcc, char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if (smb_mbc_encode(&sr->reply, fmt, ap) != 0) { - va_end(ap); - smbsr_encode_error(sr); - /* NOTREACHED */ - } - va_end(ap); - /*LINTED E_ASSIGN_NARROW_CONV*/ - sr->smb_wct = wct; - /*LINTED E_ASSIGN_NARROW_CONV*/ - sr->smb_bcc = bcc; -} - -int smb_peek_mbc(struct mbuf_chain *mbc, int offset, char *fmt, ...) { int xx; diff --git a/usr/src/uts/common/fs/smbsrv/smb_move.c b/usr/src/uts/common/fs/smbsrv/smb_move.c index eb44e5a84d..d11a5c4049 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_move.c +++ b/usr/src/uts/common/fs/smbsrv/smb_move.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -102,13 +102,10 @@ */ #include <smbsrv/smb_incl.h> + /*ARGSUSED*/ -int +smb_sdrc_t smb_com_move(struct smb_request *sr) { - /* TODO move */ - /* TODO move wildcards */ - /* TODO move */ - return (SDRC_UNIMPLEMENTED); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_negotiate.c b/usr/src/uts/common/fs/smbsrv/smb_negotiate.c index a14ae7d3a5..e1d65283aa 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_negotiate.c +++ b/usr/src/uts/common/fs/smbsrv/smb_negotiate.c @@ -240,7 +240,7 @@ static void smb_get_security_info( * Function: int smb_com_negotiate(struct smb_request *) */ -int +smb_sdrc_t smb_com_negotiate(struct smb_request *sr) { int dialect = 0; @@ -254,6 +254,7 @@ smb_com_negotiate(struct smb_request *sr) unsigned short secmode; uint32_t sesskey; uint32_t capabilities = 0; + int rc; unsigned short max_mpx_count; WORD tz_correction; @@ -262,7 +263,7 @@ smb_com_negotiate(struct smb_request *sr) if (sr->session->s_state != SMB_SESSION_STATE_ESTABLISHED) { /* The protocol has already been negotiated. */ smbsr_error(sr, 0, ERRSRV, ERRerror); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } for (pos = 0; @@ -270,7 +271,7 @@ smb_com_negotiate(struct smb_request *sr) pos++) { if (smb_decode_mbc(&sr->smb_data, "%L", sr, &p) != 0) { smbsr_error(sr, 0, ERRSRV, ERRerror); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } this_dialect = smb_xlate_dialect_str_to_cd(p); @@ -285,7 +286,7 @@ smb_com_negotiate(struct smb_request *sr) } if (sel_pos < 0) { smbsr_error(sr, 0, ERRSRV, ERRerror); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } smb_get_security_info(sr, &secmode, (unsigned char *)key, @@ -301,7 +302,7 @@ smb_com_negotiate(struct smb_request *sr) (void) sosetsockopt(sr->session->sock, SOL_SOCKET, SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf, sizeof (smb_dos_tcp_rcvbuf)); - smbsr_encode_result(sr, 1, 0, "bww", 1, sel_pos, 0); + rc = smbsr_encode_result(sr, 1, 0, "bww", 1, sel_pos, 0); break; case Windows_for_Workgroups_3_1a: @@ -315,7 +316,7 @@ smb_com_negotiate(struct smb_request *sr) (const void *)&smb_dos_tcp_rcvbuf, sizeof (smb_dos_tcp_rcvbuf)); sr->smb_flg |= SMB_FLAGS_LOCK_AND_READ_OK; - smbsr_encode_result(sr, 13, VAR_BCC, + rc = smbsr_encode_result(sr, 13, VAR_BCC, "(wct) b" "(dix) w" "(sec) w" "(mbs) w" "(mmc) w" "(mnv) w" "(raw) w" "(key) l" "(tim/dat) Y" "(tz) w" "(ekl) w" @@ -343,7 +344,7 @@ smb_com_negotiate(struct smb_request *sr) (const void *)&smb_dos_tcp_rcvbuf, sizeof (smb_dos_tcp_rcvbuf)); sr->smb_flg |= SMB_FLAGS_LOCK_AND_READ_OK; - smbsr_encode_result(sr, 13, VAR_BCC, + rc = smbsr_encode_result(sr, 13, VAR_BCC, "(wct) b" "(dix) w" "(sec) w" "(mbs) w" "(mmc) w" "(mnv) w" "(raw) w" "(key) l" "(tim/dat) Y" "(tz) w" "(ekl) w" @@ -411,7 +412,7 @@ smb_com_negotiate(struct smb_request *sr) /*LINTED E_ASSIGN_NARROW_CONV (uint16_t)*/ max_mpx_count = smb_info.si.skc_maxworkers; - smbsr_encode_result(sr, 17, VAR_BCC, + rc = smbsr_encode_result(sr, 17, VAR_BCC, "(wct) b" "(dix) w" "(sec) b" "(mmc) w" "(mnv) w" "(mbs) l" "(raw) l" "(key) l" "(cap) l" "(tim) T" "(tz) w" "(ekl) b" @@ -436,9 +437,12 @@ smb_com_negotiate(struct smb_request *sr) default: smbsr_error(sr, 0, ERRSRV, ERRerror); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } + if (rc != 0) + return (SDRC_ERROR_REPLY); + /* * Save the agreed dialect. Note that this value is also * used to detect and reject attempts to re-negotiate. diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c b/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c index 79334395f0..613974c796 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,7 +45,7 @@ #include <smbsrv/smb_incl.h> -int +smb_sdrc_t smb_com_nt_cancel(struct smb_request *sr) { struct smb_request *req; diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c index e7dbe26746..51e3b20937 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c @@ -167,7 +167,7 @@ * SMB_COM_READ SMB_COM_READ_ANDX * SMB_COM_IOCTL */ -int +smb_sdrc_t smb_com_nt_create_andx(struct smb_request *sr) { struct open_param *op = &sr->arg.open; @@ -181,8 +181,6 @@ smb_com_nt_create_andx(struct smb_request *sr) unsigned short NameLength; smb_attr_t new_attr; smb_node_t *node; - DWORD status; - int count; int rc; op->dsize = 0; @@ -200,25 +198,21 @@ smb_com_nt_create_andx(struct smb_request *sr) &ImpersonationLevel, &SecurityFlags); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); if (NameLength >= MAXPATHLEN) { smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - if (smbsr_decode_data(sr, "%#u", sr, NameLength, &op->fqi.path) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_data(sr, "%#u", sr, NameLength, &op->fqi.path) != 0) + return (SDRC_ERROR_REPLY); if ((op->create_options & FILE_DELETE_ON_CLOSE) && !(op->desired_access & DELETE)) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } op->fqi.srch_attr = 0; @@ -255,42 +249,15 @@ smb_com_nt_create_andx(struct smb_request *sr) if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } op->fqi.dir_snode = sr->fid_ofile->f_node; smbsr_disconnect_file(sr); } - status = NT_STATUS_SUCCESS; - /* - * According to NT, when exclusive share access failed, - * instead of raising "access deny" error immediately, - * we should wait for the client holding the exclusive - * file to close the file. If the wait timed out, we - * report a sharing violation; otherwise, we grant access. - * smb_open_subr returns NT_STATUS_SHARING_VIOLATION when - * it encounters an exclusive share access deny: we wait - * and retry. - */ - for (count = 0; count <= 4; count++) { - if (count) { - delay(MSEC_TO_TICK(400)); - } - - if ((status = smb_open_subr(sr)) == NT_STATUS_SUCCESS) - break; - } - - if (status != NT_STATUS_SUCCESS) { - if (status == NT_STATUS_SHARING_VIOLATION) - smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, - ERRDOS, ERROR_SHARING_VIOLATION); - else - smbsr_error(sr, status, 0, 0); - - /* NOTREACHED */ - } + if (smb_common_open(sr) != NT_STATUS_SUCCESS) + return (SDRC_ERROR_REPLY); if (STYPE_ISDSK(sr->tid_tree->t_res_type)) { switch (MYF_OPLOCK_TYPE(op->my_flags)) { @@ -327,7 +294,7 @@ smb_com_nt_create_andx(struct smb_request *sr) node->attr.sa_vattr.va_size = new_attr.sa_vattr.va_size; } - smbsr_encode_result(sr, 34, 0, "bb.wbwlTTTTlqqwwbw", + rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlTTTTlqqwwbw", 34, sr->andx_com, 0x67, @@ -348,7 +315,7 @@ smb_com_nt_create_andx(struct smb_request *sr) } else { /* Named PIPE */ OplockLevel = 0; - smbsr_encode_result(sr, 34, 0, "bb.wbwlqqqqlqqwwbw", + rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlqqqqlqqwwbw", 34, sr->andx_com, 0x67, @@ -368,5 +335,5 @@ smb_com_nt_create_andx(struct smb_request *sr) 0); } - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c index d844733b36..c3439666ac 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c @@ -58,7 +58,7 @@ * security descriptor. For information not defined in CIFS section 4.2.2 * see section 4.2.1 (NT_CREATE_ANDX). */ -int +smb_sdrc_t smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa) { struct open_param *op = &sr->arg.open; @@ -94,10 +94,8 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa) &ImpersonationLevel, &SecurityFlags); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); /* * If name length is zero, interpret as "\". @@ -107,23 +105,21 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa) } else { rc = smb_decode_mbc(&xa->req_param_mb, "%#u", sr, NameLength, &op->fqi.path); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); } if ((op->create_options & FILE_DELETE_ON_CLOSE) && !(op->desired_access & DELETE)) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (sd_len) { status = smb_decode_sd(xa, &sd); if (status != NT_STATUS_SUCCESS) { smbsr_error(sr, status, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } op->sd = &sd; } else { @@ -171,19 +167,13 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa) smbsr_disconnect_file(sr); } - status = smb_open_subr(sr); + status = smb_common_open(sr); + if (op->sd) smb_sd_term(op->sd); - if (status != NT_STATUS_SUCCESS) { - if (status == NT_STATUS_SHARING_VIOLATION) - smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, - ERRDOS, ERROR_SHARING_VIOLATION); - else - smbsr_error(sr, status, 0, 0); - - /* NOTREACHED */ - } + if (status != NT_STATUS_SUCCESS) + return (SDRC_ERROR_REPLY); if (STYPE_ISDSK(sr->tid_tree->t_res_type)) { switch (MYF_OPLOCK_TYPE(op->my_flags)) { diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c index 16fbdbede8..2a1443849d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c @@ -32,14 +32,14 @@ /* * This table defines the list of IOCTL/FSCTL values for which we'll - * return a specific NT status code, based on observation of NT. + * return a specific NT status code. */ static struct { uint32_t fcode; DWORD status; } ioctl_ret_tbl[] = { - {FSCTL_GET_OBJECT_ID, NT_STATUS_INVALID_PARAMETER}, - {FSCTL_QUERY_ALLOCATED_RANGES, NT_STATUS_INVALID_PARAMETER} + { FSCTL_GET_OBJECT_ID, NT_STATUS_INVALID_PARAMETER }, + { FSCTL_QUERY_ALLOCATED_RANGES, NT_STATUS_INVALID_PARAMETER } }; @@ -75,7 +75,7 @@ static struct { * io or fs control. * Data[ DataCount ] The results of the io or fs control. */ -int +smb_sdrc_t smb_nt_transact_ioctl(struct smb_request *sr, struct smb_xa *xa) { DWORD status = NT_STATUS_SUCCESS; @@ -86,15 +86,12 @@ smb_nt_transact_ioctl(struct smb_request *sr, struct smb_xa *xa) int i; if (smb_decode_mbc(&xa->req_setup_mb, "lwbb", - &fcode, - &fid, - &is_fsctl, - &is_flags) != 0) { + &fcode, &fid, &is_fsctl, &is_flags) != 0) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); + return (SDRC_ERROR_REPLY); } - for (i = 0; - i < sizeof (ioctl_ret_tbl) / sizeof (ioctl_ret_tbl[0]); + for (i = 0; i < sizeof (ioctl_ret_tbl) / sizeof (ioctl_ret_tbl[0]); i++) { if (ioctl_ret_tbl[i].fcode == fcode) { status = ioctl_ret_tbl[i].status; @@ -102,8 +99,10 @@ smb_nt_transact_ioctl(struct smb_request *sr, struct smb_xa *xa) } } - if (status != NT_STATUS_SUCCESS) + if (status != NT_STATUS_SUCCESS) { smbsr_error(sr, status, 0, 0); + return (SDRC_ERROR_REPLY); + } (void) smb_encode_mbc(&xa->rep_param_mb, "l", 0); return (SDRC_NORMAL_REPLY); diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c index 264a078a48..0d502e1827 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c @@ -114,6 +114,8 @@ #include <smbsrv/smb_incl.h> #include <sys/sdt.h> +static void smb_reply_notify_change_request(smb_request_t *); + /* * smb_nt_transact_notify_change * @@ -122,7 +124,7 @@ * a monitored directory is changed or client cancels one of its already * sent requests. */ -int +smb_sdrc_t smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) { uint32_t CompletionFilter; @@ -136,7 +138,7 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } node = sr->fid_ofile->f_node; @@ -146,7 +148,7 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) * Notify change requests are only valid on directories. */ smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } mutex_enter(&sr->sr_mutex); @@ -191,7 +193,8 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) case SMB_REQ_STATE_CANCELED: mutex_exit(&sr->sr_mutex); smbsr_error(sr, NT_STATUS_CANCELLED, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); + default: ASSERT(0); mutex_exit(&sr->sr_mutex); @@ -208,7 +211,7 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) * If client cancels the request or session dropped, an NT_STATUS_CANCELED * is sent in reply. */ -int +static void smb_reply_notify_change_request(smb_request_t *sr) { smb_node_t *node; @@ -250,7 +253,7 @@ smb_reply_notify_change_request(smb_request_t *sr) data_off = param_off + n_param + data_pad; total_bytes = param_pad + n_param + data_pad + n_data; - smbsr_encode_result(sr, 18+n_setup, total_bytes, + (void) smbsr_encode_result(sr, 18+n_setup, total_bytes, "b 3. llllllllb C w #. C #. C", 18 + n_setup, /* wct */ n_param, /* Total Parameter Bytes */ @@ -314,7 +317,6 @@ smb_reply_notify_change_request(smb_request_t *sr) sr->sr_state = SMB_REQ_STATE_COMPLETED; mutex_exit(&sr->sr_mutex); smb_request_free(sr); - return (0); } /* @@ -556,7 +558,7 @@ smb_notify_change_daemon(smb_thread_t *thread, void *si_void) ASSERT(sr->sr_magic == SMB_REQ_MAGIC); tmp = list_next(&sr_list, sr); list_remove(&sr_list, sr); - (void) smb_reply_notify_change_request(sr); + smb_reply_notify_change_request(sr); sr = tmp; } } diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c index 69ea40bdb3..cc36dd8282 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c @@ -67,7 +67,7 @@ static smb_acl_t *smb_decode_acl(struct smb_xa *, uint32_t); * Data[TotalDataCount] Security Descriptor information */ -int +smb_sdrc_t smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) { smb_sd_t sd; @@ -79,13 +79,13 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) if (smb_decode_mbc(&xa->req_param_mb, "w2.l", &sr->smb_fid, &secinfo) != 0) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } @@ -93,7 +93,7 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (sr->tid_tree->t_acltype != ACE_T) { @@ -107,14 +107,14 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) status = smb_sd_read(sr, &sd, secinfo); if (status != NT_STATUS_SUCCESS) { smbsr_error(sr, status, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sdlen = smb_sd_len(&sd, secinfo); if (sdlen == 0) { smb_sd_term(&sd); smbsr_error(sr, NT_STATUS_INVALID_SECURITY_DESCR, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (sdlen > xa->smb_mdrcnt) { @@ -159,7 +159,7 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) * ================================== ================================== * Data[TotalDataCount] Security Descriptor information */ -int +smb_sdrc_t smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) { smb_sd_t sd; @@ -169,24 +169,24 @@ smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) if (smb_decode_mbc(&xa->req_param_mb, "w2.l", &sr->smb_fid, &secinfo) != 0) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if ((sr->fid_ofile->f_node == NULL) || (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (sr->fid_ofile->f_node->flags & NODE_READ_ONLY) { smbsr_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (sr->tid_tree->t_acltype != ACE_T) { @@ -204,20 +204,20 @@ smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) status = smb_decode_sd(xa, &sd); if (status != NT_STATUS_SUCCESS) { smbsr_error(sr, status, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) || ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } status = smb_sd_write(sr, &sd, secinfo); smb_sd_term(&sd); if (status != NT_STATUS_SUCCESS) { smbsr_error(sr, status, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } return (SDRC_NORMAL_REPLY); diff --git a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c index 486422d9c5..e693ce43e4 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c @@ -223,23 +223,20 @@ * read nor write the file. */ -int +smb_sdrc_t smb_com_open(struct smb_request *sr) { struct open_param *op = &sr->arg.open; uint16_t file_attr; - DWORD status; + int rc; bzero(op, sizeof (sr->arg.open)); - if (smbsr_decode_vwv(sr, "ww", &op->omode, &op->fqi.srch_attr) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "ww", &op->omode, &op->fqi.srch_attr) != 0) + return (SDRC_ERROR_REPLY); + + if (smbsr_decode_data(sr, "%S", sr, &op->fqi.path) != 0) + return (SDRC_ERROR_REPLY); - if (smbsr_decode_data(sr, "%S", sr, &op->fqi.path) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } op->desired_access = smb_omode_to_amask(op->omode); op->share_access = smb_denymode_to_sharemode(op->omode, op->fqi.path); @@ -247,7 +244,7 @@ smb_com_open(struct smb_request *sr) (op->share_access == ((uint32_t)SMB_INVALID_SHAREMODE))) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } op->dsize = 0; /* Don't set spurious size */ @@ -264,27 +261,22 @@ smb_com_open(struct smb_request *sr) } } - if ((status = smb_open_subr(sr)) != NT_STATUS_SUCCESS) { - if (status == NT_STATUS_SHARING_VIOLATION) - smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, - ERRDOS, ERROR_SHARING_VIOLATION); - else - smbsr_error(sr, status, 0, 0); - - /* NOTREACHED */ - } + if (smb_common_open(sr) != NT_STATUS_SUCCESS) + return (SDRC_ERROR_REPLY); if (MYF_OPLOCK_TYPE(op->my_flags) == MYF_OPLOCK_NONE) { sr->smb_flg &= ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY); } - if (op->dsize > UINT_MAX) + if (op->dsize > UINT_MAX) { smbsr_error(sr, 0, ERRDOS, ERRbadfunc); + return (SDRC_ERROR_REPLY); + } file_attr = op->dattr & FILE_ATTRIBUTE_MASK; - smbsr_encode_result(sr, 7, 0, "bwwllww", + rc = smbsr_encode_result(sr, 7, 0, "bwwllww", 7, sr->smb_fid, file_attr, @@ -293,10 +285,10 @@ smb_com_open(struct smb_request *sr) op->omode & SMB_DA_ACCESS_MASK, (uint16_t)0); /* bcc */ - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } -int +smb_sdrc_t smb_com_open_andx(struct smb_request *sr) { struct open_param *op = &sr->arg.open; @@ -305,8 +297,6 @@ smb_com_open_andx(struct smb_request *sr) uint16_t granted_access; uint16_t ofun; uint16_t file_attr; - int count; - DWORD status; int rc; bzero(op, sizeof (sr->arg.open)); @@ -314,15 +304,11 @@ smb_com_open_andx(struct smb_request *sr) rc = smbsr_decode_vwv(sr, "b.wwwwwlwll4.", &sr->andx_com, &sr->andx_off, &flags, &op->omode, &op->fqi.srch_attr, &file_attr, &CreationTime, &ofun, &op->dsize, &op->timeo); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); - if (smbsr_decode_data(sr, "%u", sr, &op->fqi.path) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_data(sr, "%u", sr, &op->fqi.path) != 0) + return (SDRC_ERROR_REPLY); op->desired_access = smb_omode_to_amask(op->omode); op->share_access = smb_denymode_to_sharemode(op->omode, op->fqi.path); @@ -331,14 +317,14 @@ smb_com_open_andx(struct smb_request *sr) (op->share_access == ((uint32_t)SMB_INVALID_SHAREMODE))) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } op->dattr = file_attr; op->create_disposition = smb_ofun_to_crdisposition(ofun); if (op->create_disposition == ((uint32_t)SMB_INVALID_CRDISPOSITION)) { smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_PARAMETER); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } op->create_options = (op->omode & SMB_DA_WRITE_THROUGH) @@ -353,38 +339,13 @@ smb_com_open_andx(struct smb_request *sr) op->utime.tv_sec = smb_local_time_to_gmt(CreationTime); op->utime.tv_nsec = 0; - status = NT_STATUS_SUCCESS; - /* - * According to NT, when exclusive share access failed, - * instead of raising "access deny" error immediately, - * we should wait for the client holding the exclusive - * file to close the file. If the wait timed out, we - * report a sharing violation; otherwise, we grant access. - * smb_open_subr returns NT_STATUS_SHARING_VIOLATION when - * it encounters an exclusive share access deny: we wait - * and retry. - */ - for (count = 0; count <= 4; count++) { - if (count) { - delay(MSEC_TO_TICK(400)); - } - - if ((status = smb_open_subr(sr)) == NT_STATUS_SUCCESS) - break; - } - - if (status != NT_STATUS_SUCCESS) { - if (status == NT_STATUS_SHARING_VIOLATION) - smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, - ERRDOS, ERROR_SHARING_VIOLATION); - else - smbsr_error(sr, status, 0, 0); - - /* NOTREACHED */ - } + if (smb_common_open(sr) != NT_STATUS_SUCCESS) + return (SDRC_ERROR_REPLY); - if (op->dsize > UINT_MAX) + if (op->dsize > UINT_MAX) { smbsr_error(sr, 0, ERRDOS, ERRbadfunc); + return (SDRC_ERROR_REPLY); + } if (MYF_OPLOCK_TYPE(op->my_flags) != MYF_OPLOCK_NONE) { op->action_taken |= SMB_OACT_LOCK; @@ -398,7 +359,7 @@ smb_com_open_andx(struct smb_request *sr) file_attr = op->dattr & FILE_ATTRIBUTE_MASK; if (STYPE_ISDSK(sr->tid_tree->t_res_type)) { smb_node_t *node = sr->fid_ofile->f_node; - smbsr_encode_result(sr, 15, 0, + rc = smbsr_encode_result(sr, 15, 0, "b b.w w wll www wl 2. w", 15, sr->andx_com, VAR_BCC, @@ -411,7 +372,7 @@ smb_com_open_andx(struct smb_request *sr) op->action_taken, op->fileid, 0); } else { - smbsr_encode_result(sr, 15, 0, + rc = smbsr_encode_result(sr, 15, 0, "b b.w w wll www wl 2. w", 15, sr->andx_com, VAR_BCC, @@ -425,5 +386,5 @@ smb_com_open_andx(struct smb_request *sr) 0); } - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c index c31c764bf4..ba446b0f06 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c +++ b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c @@ -218,6 +218,11 @@ smb_pathname_reduce( *dir_node = NULL; *last_component = '\0'; + if (sr && sr->tid_tree) { + if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) + return (EACCES); + } + if (SMB_TREE_CASE_INSENSITIVE(sr)) lookup_flags |= FIGNORECASE; diff --git a/usr/src/uts/common/fs/smbsrv/smb_print.c b/usr/src/uts/common/fs/smbsrv/smb_print.c index 13f3746b06..ff865fdc2d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_print.c +++ b/usr/src/uts/common/fs/smbsrv/smb_print.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -84,7 +84,7 @@ * ERRSRV/ERRqfull * ERRSRV/ERRqtoobig */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_open_print_file(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); @@ -119,7 +119,7 @@ smb_com_open_print_file(struct smb_request *sr) * other types of Fid closing requests to invalidate the Fid and begin * spooling. */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_close_print_file(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); @@ -195,17 +195,17 @@ smb_com_close_print_file(struct smb_request *sr) * ERRHRD/ERRerror * ERRSRV/ERRbaduid */ -int +smb_sdrc_t smb_com_get_print_queue(struct smb_request *sr) { unsigned short max_count, start_ix; - if (smbsr_decode_vwv(sr, "ww", &max_count, &start_ix) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "ww", &max_count, &start_ix) != 0) + return (SDRC_ERROR_REPLY); + + if (smbsr_encode_result(sr, 2, 3, "bwwwbw", 2, 0, 0, 3, 1, 0)) + return (SDRC_ERROR_REPLY); - smbsr_encode_result(sr, 2, 3, "bwwwbw", 2, 0, 0, 3, 1, 0); return (SDRC_NORMAL_REPLY); } @@ -246,7 +246,7 @@ smb_com_get_print_queue(struct smb_request *sr) * support the application of normal write requests to print spool files. * */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_write_print_file(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); diff --git a/usr/src/uts/common/fs/smbsrv/smb_process_exit.c b/usr/src/uts/common/fs/smbsrv/smb_process_exit.c index 40d49ea17f..ee43cd499d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_process_exit.c +++ b/usr/src/uts/common/fs/smbsrv/smb_process_exit.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -55,14 +55,16 @@ #include <smbsrv/smb_incl.h> -int +smb_sdrc_t smb_com_process_exit(struct smb_request *sr) { + int rc; + sr->uid_user = smb_user_lookup_by_uid(sr->session, &sr->user_cr, sr->smb_uid); if (sr->uid_user == NULL) { - smbsr_encode_empty_result(sr); - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } /* @@ -79,6 +81,6 @@ smb_com_process_exit(struct smb_request *sr) smb_tree_close_all_by_pid(sr->uid_user, sr->smb_pid); } - smbsr_encode_empty_result(sr); - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_information.c b/usr/src/uts/common/fs/smbsrv/smb_query_information.c index 391c3f9c24..0e8fb3019c 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_information.c @@ -65,7 +65,7 @@ #include <smbsrv/smb_incl.h> #include <smbsrv/smb_fsops.h> -int +smb_sdrc_t smb_com_query_information(struct smb_request *sr) { int rc; @@ -78,25 +78,31 @@ smb_com_query_information(struct smb_request *sr) char *name; timestruc_t *mtime; - name = kmem_alloc(MAXNAMELEN, KM_SLEEP); - if (smbsr_decode_data(sr, "%S", sr, &path) != 0) { - kmem_free(name, MAXNAMELEN); - smbsr_decode_error(sr); - /* NOTREACHED */ + if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { + dattr = SMB_FA_NORMAL; + write_time = file_size = 0; + rc = smbsr_encode_result(sr, 10, 0, "bwll10.w", + 10, dattr, write_time, file_size, 0); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } + if (smbsr_decode_data(sr, "%S", sr, &path) != 0) + return (SDRC_ERROR_REPLY); + /* - * Some MS clients pass NULL file names - * NT interprets this as "\" + * Interpret NULL file names as "\". */ - if (strlen(path) == 0) path = "\\"; + if (strlen(path) == 0) + path = "\\"; + + name = kmem_alloc(MAXNAMELEN, KM_SLEEP); if ((rc = smb_pathname_reduce(sr, sr->user_cr, path, sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dir_node, name)) != 0) { kmem_free(name, MAXNAMELEN); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if ((rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, @@ -104,7 +110,7 @@ smb_com_query_information(struct smb_request *sr) smb_node_release(dir_node); kmem_free(name, MAXNAMELEN); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } smb_node_release(dir_node); @@ -115,14 +121,14 @@ smb_com_query_information(struct smb_request *sr) file_size = (uint32_t)smb_node_get_size(node, &node->attr); smb_node_release(node); + kmem_free(name, MAXNAMELEN); - smbsr_encode_result(sr, 10, 0, "bwll10.w", + rc = smbsr_encode_result(sr, 10, 0, "bwll10.w", 10, /* wct */ dattr, write_time, /* Last write time */ file_size, /* FileSize */ 0); /* bcc */ - kmem_free(name, MAXNAMELEN); - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_information2.c b/usr/src/uts/common/fs/smbsrv/smb_query_information2.c index d6fa3d1f26..0f5f5018ab 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_information2.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_information2.c @@ -61,29 +61,28 @@ #include <smbsrv/smb_incl.h> -int +smb_sdrc_t smb_com_query_information2(struct smb_request *sr) { smb_node_t *node; smb_attr_t *attr; uint32_t dsize, dasize; unsigned short dattr; + int rc; - if (smbsr_decode_vwv(sr, "w", &sr->smb_fid) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "w", &sr->smb_fid) != 0) + return (SDRC_ERROR_REPLY); sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } node = sr->fid_ofile->f_node; @@ -93,7 +92,7 @@ smb_com_query_information2(struct smb_request *sr) dasize = attr->sa_vattr.va_blksize * attr->sa_vattr.va_nblocks; dsize = (dattr & SMB_FA_DIRECTORY) ? 0 : attr->sa_vattr.va_size; - smbsr_encode_result(sr, 11, 0, "byyyllww", + rc = smbsr_encode_result(sr, 11, 0, "byyyllww", 11, /* wct */ smb_gmt_to_local_time(attr->sa_crtime.tv_sec), /* LastAccessTime */ @@ -105,5 +104,5 @@ smb_com_query_information2(struct smb_request *sr) dattr, /* FileAttributes */ 0); /* bcc */ - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_information_disk.c b/usr/src/uts/common/fs/smbsrv/smb_query_information_disk.c index 6e38758502..802e74d06f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_information_disk.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_information_disk.c @@ -67,7 +67,7 @@ #include <smbsrv/smb_incl.h> #include <smbsrv/smb_fsops.h> -int +smb_sdrc_t smb_com_query_information_disk(struct smb_request *sr) { int rc; @@ -77,9 +77,16 @@ smb_com_query_information_disk(struct smb_request *sr) unsigned short blocks_per_unit, bytes_per_block; unsigned short total_units, free_units; - if ((rc = smb_fsop_statfs(sr->user_cr, sr->tid_tree->t_snode, &df)) - != 0) + if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); + return (SDRC_ERROR_REPLY); + } + + rc = smb_fsop_statfs(sr->user_cr, sr->tid_tree->t_snode, &df); + if (rc != 0) { smbsr_errno(sr, rc); + return (SDRC_ERROR_REPLY); + } unit_size = 1; block_size = df.f_frsize; @@ -117,7 +124,7 @@ smb_com_query_information_disk(struct smb_request *sr) bytes_per_block = (unsigned short)block_size; blocks_per_unit = (unsigned short)unit_size; - smbsr_encode_result(sr, 5, 0, "bwwww2.w", + rc = smbsr_encode_result(sr, 5, 0, "bwwww2.w", 5, total_units, /* total_units */ blocks_per_unit, /* blocks_per_unit */ @@ -125,5 +132,5 @@ smb_com_query_information_disk(struct smb_request *sr) free_units, /* free_units */ 0); /* bcc */ - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_read.c b/usr/src/uts/common/fs/smbsrv/smb_read.c index fda5c6fdca..7b7aeffa5c 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_read.c +++ b/usr/src/uts/common/fs/smbsrv/smb_read.c @@ -37,7 +37,7 @@ typedef struct smb_read_param { } smb_read_param_t; -int smb_common_read(struct smb_request *sr, smb_read_param_t *param); +int smb_common_read(struct smb_request *, smb_read_param_t *); /* @@ -55,7 +55,7 @@ int smb_common_read(struct smb_request *sr, smb_read_param_t *param); * length response is generated. A count returned which is less than the * count requested is the end of file indicator. */ -int +smb_sdrc_t smb_com_read(struct smb_request *sr) { smb_read_param_t param; @@ -65,10 +65,8 @@ smb_com_read(struct smb_request *sr) rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, ¶m.r_count, &off_low, &remcnt); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); param.r_offset = (uint64_t)off_low; param.r_mincnt = 0; @@ -76,18 +74,18 @@ smb_com_read(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if ((rc = smb_common_read(sr, ¶m)) != 0) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", + rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 5, param.r_count, VAR_BCC, 0x01, param.r_count, &sr->raw_data); - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } /* @@ -112,7 +110,7 @@ smb_com_read(struct smb_request *sr) * length response is generated. A count returned which is less than the * count requested is the end of file indicator. */ -int +smb_sdrc_t smb_com_lock_and_read(struct smb_request *sr) { smb_read_param_t param; @@ -123,15 +121,13 @@ smb_com_lock_and_read(struct smb_request *sr) if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, ¶m.r_count, &off_low, &remcnt); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); param.r_offset = (uint64_t)off_low; param.r_mincnt = 0; @@ -139,24 +135,25 @@ smb_com_lock_and_read(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } result = smb_lock_range(sr, sr->fid_ofile, param.r_offset, (uint64_t)param.r_count, UINT_MAX, SMB_LOCK_TYPE_READWRITE); if (result != NT_STATUS_SUCCESS) { smb_lock_range_error(sr, result); + return (SDRC_ERROR_REPLY); } if ((rc = smb_common_read(sr, ¶m)) != 0) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", + rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 5, param.r_count, VAR_BCC, 0x1, param.r_count, &sr->raw_data); - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } /* @@ -180,7 +177,7 @@ smb_com_lock_and_read(struct smb_request *sr) * * Read errors are handled by sending a zero length response. */ -int +smb_sdrc_t smb_com_read_raw(struct smb_request *sr) { smb_read_param_t param; @@ -204,17 +201,15 @@ smb_com_read_raw(struct smb_request *sr) param.r_offset = ((uint64_t)off_high << 32) | off_low; } - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } rc = smb_common_read(sr, ¶m); @@ -267,7 +262,7 @@ smb_com_read_raw(struct smb_request *sr) * LM 0.12 to support 64-bit offsets, indicated by sending a wct of * 12 and including additional offset information. */ -int +smb_sdrc_t smb_com_read_andx(struct smb_request *sr) { smb_read_param_t param; @@ -290,22 +285,20 @@ smb_com_read_andx(struct smb_request *sr) param.r_offset = (uint64_t)off_low; } - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); param.r_mincnt = 0; sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if ((rc = smb_common_read(sr, ¶m)) != 0) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } /* @@ -320,7 +313,7 @@ smb_com_read_andx(struct smb_request *sr) * is a follow-up to an earlier RPC transaction. */ if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { - smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.ww10.wbC", + rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.ww10.wbC", 12, /* wct */ secondary, /* Secondary andx command */ offset2, /* offset to next */ @@ -331,7 +324,7 @@ smb_com_read_andx(struct smb_request *sr) 0x02, /* unknown */ &sr->raw_data); } else { - smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.ww10.wC", + rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.ww10.wC", 12, /* wct */ secondary, /* Secondary andx command */ offset2, /* offset to next */ @@ -342,7 +335,7 @@ smb_com_read_andx(struct smb_request *sr) &sr->raw_data); } - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } /* @@ -439,14 +432,14 @@ smb_common_read(struct smb_request *sr, smb_read_param_t *param) * only over connectionless transports. */ /*ARGSUSED*/ -int +smb_sdrc_t smb_com_read_mpx(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); } /*ARGSUSED*/ -int +smb_sdrc_t smb_com_read_mpx_secondary(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); diff --git a/usr/src/uts/common/fs/smbsrv/smb_rename.c b/usr/src/uts/common/fs/smbsrv/smb_rename.c index 0239635663..f7a9946972 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_rename.c +++ b/usr/src/uts/common/fs/smbsrv/smb_rename.c @@ -53,7 +53,7 @@ static int smb_do_rename(struct smb_request *sr, * renamed. The encoding of SearchAttributes is described in section 3.10 * - File Attribute Encoding. */ -int +smb_sdrc_t smb_com_rename(struct smb_request *sr) { static kmutex_t mutex; @@ -65,22 +65,18 @@ smb_com_rename(struct smb_request *sr) if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } src_fqi = &sr->arg.dirop.fqi; dst_fqi = &sr->arg.dirop.dst_fqi; - if (smbsr_decode_vwv(sr, "w", &src_fqi->srch_attr) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "w", &src_fqi->srch_attr) != 0) + return (SDRC_ERROR_REPLY); rc = smbsr_decode_data(sr, "%SS", sr, &src_fqi->path, &dst_fqi->path); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); dst_fqi->srch_attr = 0; @@ -101,17 +97,17 @@ smb_com_rename(struct smb_request *sr) if (rc == EEXIST) { smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION, ERRDOS, ERROR_ALREADY_EXISTS); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (rc == EPIPE) { smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (src_fqi->dir_snode) @@ -129,9 +125,8 @@ smb_com_rename(struct smb_request *sr) SMB_NULL_FQI_NODES(*src_fqi); SMB_NULL_FQI_NODES(*dst_fqi); - smbsr_encode_empty_result(sr); - - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } /* diff --git a/usr/src/uts/common/fs/smbsrv/smb_rpc.c b/usr/src/uts/common/fs/smbsrv/smb_rpc.c index 1699af471e..af540e5faf 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_rpc.c +++ b/usr/src/uts/common/fs/smbsrv/smb_rpc.c @@ -245,7 +245,7 @@ smb_rpc_initialize(struct smb_request *sr, char *pipe_name) * residual data remains in the output stream until the client claims * it or closes the pipe. */ -int +smb_sdrc_t smb_rpc_transact(struct smb_request *sr, struct uio *uio) { struct smb_xa *xa; @@ -271,7 +271,7 @@ smb_rpc_transact(struct smb_request *sr, struct uio *uio) smb_rpc_exit(pipe_info); smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERROR_INVALID_HANDLE); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } streamin = &pipe_info->input; @@ -290,7 +290,7 @@ smb_rpc_transact(struct smb_request *sr, struct uio *uio) smb_rpc_exit(pipe_info); smbsr_error(sr, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID, 0, 0); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } /* diff --git a/usr/src/uts/common/fs/smbsrv/smb_search.c b/usr/src/uts/common/fs/smbsrv/smb_search.c index d0411e1e58..0a46f8587f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_search.c +++ b/usr/src/uts/common/fs/smbsrv/smb_search.c @@ -130,7 +130,7 @@ #include <smbsrv/smb_incl.h> -int +smb_sdrc_t smb_com_search(struct smb_request *sr) { int rc; @@ -150,20 +150,16 @@ smb_com_search(struct smb_request *sr) sr->smb_flg2 &= ~SMB_FLAGS2_KNOWS_LONG_NAMES; sr->smb_flg &= ~SMB_FLAGS_CASE_INSENSITIVE; - if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) + return (SDRC_ERROR_REPLY); - if ((smbsr_decode_data(sr, "%Abw", sr, &path, &type, &key_len) != 0) || - (type != 0x05)) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + rc = smbsr_decode_data(sr, "%Abw", sr, &path, &type, &key_len); + if ((rc != 0) || (type != 0x05)) + return (SDRC_ERROR_REPLY); if ((rc = fsd_getattr(&sr->tid_tree->t_fsd, &vol_attr)) != 0) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } count = 0; @@ -193,10 +189,12 @@ smb_com_search(struct smb_request *sr) if (strlen(path) == 0) path = "\\"; rc = smb_rdir_open(sr, path, sattr); - if (rc == SDRC_NORMAL_REPLY) { + if (rc == -1) + return (SDRC_ERROR_REPLY); + if (rc == -2) { sr->reply.chain_offset = sr->cur_reply_offset; (void) smb_encode_mbc(&sr->reply, "bw", 0, 0); - return (rc); + return (SDRC_NORMAL_REPLY); } resume_char = 0; resume_key = 0; @@ -205,8 +203,7 @@ smb_com_search(struct smb_request *sr) &resume_char, &cookie, &sr->smb_sid, &resume_key) != 0) { /* We don't know which search to close! */ - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, @@ -214,12 +211,11 @@ smb_com_search(struct smb_request *sr) if (sr->sid_odir == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } } else { /* We don't know which search to close! */ - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } (void) smb_encode_mbc(&sr->reply, "bwwbw", 1, 0, VAR_BCC, 5, 0); @@ -270,13 +266,13 @@ smb_com_search(struct smb_request *sr) /* returned error by smb_rdir_next() */ smb_rdir_close(sr); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (count == 0) { smb_rdir_close(sr); smbsr_error(sr, 0, ERRDOS, ERRnofiles); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } } diff --git a/usr/src/uts/common/fs/smbsrv/smb_seek.c b/usr/src/uts/common/fs/smbsrv/smb_seek.c index cffb9ce2d0..fab979cdd6 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_seek.c +++ b/usr/src/uts/common/fs/smbsrv/smb_seek.c @@ -79,7 +79,7 @@ * end of file. An attempt to seek before the start of the file sets the * current file pointer to the start of the file. */ -int +smb_sdrc_t smb_com_seek(struct smb_request *sr) { ushort_t mode; @@ -87,31 +87,30 @@ smb_com_seek(struct smb_request *sr) uint32_t off_ret; int rc; - if (smbsr_decode_vwv(sr, "wwl", &sr->smb_fid, &mode, &off) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "wwl", &sr->smb_fid, &mode, &off) != 0) + return (SDRC_ERROR_REPLY); sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - if (mode == SMB_SEEK_END) { + if (mode == SMB_SEEK_END) (void) smb_set_file_size(sr); - } if ((rc = smb_ofile_seek(sr->fid_ofile, mode, off, &off_ret)) != 0) { if (rc == EINVAL) { smbsr_error(sr, 0, ERRDOS, ERRbadfunc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } else { smbsr_error(sr, 0, ERRSRV, ERRerror); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } } - smbsr_encode_result(sr, 2, 0, "blw", 2, off_ret, 0); + if (smbsr_encode_result(sr, 2, 0, "blw", 2, off_ret, 0)) + return (SDRC_ERROR_REPLY); + return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_session.c b/usr/src/uts/common/fs/smbsrv/smb_session.c index 9642aaa76d..00197b76d9 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_session.c +++ b/usr/src/uts/common/fs/smbsrv/smb_session.c @@ -1136,16 +1136,7 @@ smb_session_worker( switch (sr->sr_state) { case SMB_REQ_STATE_SUBMITTED: mutex_exit(&sr->sr_mutex); - if (smb_dispatch_request(sr) < 0) { - smb_rwx_rwenter(&sr->session->s_lock, RW_WRITER); - if (sr->session->s_state != - SMB_SESSION_STATE_DISCONNECTED) { - smb_soshutdown(sr->session->sock); - sr->session->s_state = - SMB_SESSION_STATE_DISCONNECTED; - } - smb_rwx_rwexit(&sr->session->s_lock); - } + smb_dispatch_request(sr); mutex_enter(&sr->sr_mutex); if (!sr->sr_keep) { sr->sr_state = SMB_REQ_STATE_COMPLETED; diff --git a/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c b/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c index 887a0ca648..e3ec42e912 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c @@ -227,7 +227,7 @@ #include <smbsrv/smb_token.h> #include <smbsrv/smb_door_svc.h> -int +smb_sdrc_t smb_com_session_setup_andx(struct smb_request *sr) { uint16_t maxbufsize, maxmpxcount, vcnumber = 0; @@ -256,10 +256,8 @@ smb_com_session_setup_andx(struct smb_request *sr) &sr->andx_off, &maxbufsize, &maxmpxcount, &vcnumber, &sesskey, &ci_pwlen, &cs_pwlen, &capabilities); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); ci_password = kmem_alloc(ci_pwlen + 1, KM_SLEEP); cs_password = kmem_alloc(cs_pwlen + 1, KM_SLEEP); @@ -288,8 +286,7 @@ smb_com_session_setup_andx(struct smb_request *sr) if (rc != 0) { kmem_free(ci_password, ci_pwlen + 1); kmem_free(cs_password, cs_pwlen + 1); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } ci_password[ci_pwlen] = 0; @@ -315,17 +312,14 @@ smb_com_session_setup_andx(struct smb_request *sr) &sr->andx_off, &maxbufsize, &maxmpxcount, &vcnumber, &sesskey, &ci_pwlen); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); ci_password = kmem_alloc(ci_pwlen + 1, KM_SLEEP); rc = smbsr_decode_data(sr, "%#c", sr, ci_pwlen, ci_password); if (rc != 0) { kmem_free(ci_password, ci_pwlen + 1); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } ci_password[ci_pwlen] = 0; @@ -371,7 +365,7 @@ smb_com_session_setup_andx(struct smb_request *sr) if (cs_password) kmem_free(cs_password, cs_pwlen + 1); smbsr_error(sr, 0, ERRSRV, ERRaccess); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } else if (utf8_strcasecmp(primary_domain, hostname) == 0) { /* * When domain name is equal to hostname, it means @@ -430,7 +424,7 @@ smb_com_session_setup_andx(struct smb_request *sr) if (cs_password) kmem_free(cs_password, cs_pwlen + 1); smbsr_error(sr, 0, ERRSRV, ERRbadpw); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (usr_token->tkn_session_key) { @@ -462,7 +456,7 @@ smb_com_session_setup_andx(struct smb_request *sr) if (session_key) kmem_free(session_key, sizeof (smb_session_key_t)); smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE); - /* no return */ + return (SDRC_ERROR_REPLY); } sr->user_cr = user->u_cred; @@ -499,7 +493,7 @@ smb_com_session_setup_andx(struct smb_request *sr) * and I don't know if a change would cause any problems (see the * conditional test below). */ - smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu", + rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu", 3, sr->andx_com, -1, /* andx_off */ @@ -510,5 +504,5 @@ smb_com_session_setup_andx(struct smb_request *sr) "NT LAN Manager 4.0", smb_info.si.skc_resource_domain); - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_set_information.c b/usr/src/uts/common/fs/smbsrv/smb_set_information.c index e7b1237fa9..c6c4375518 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_set_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_set_information.c @@ -58,7 +58,7 @@ #include <smbsrv/smb_incl.h> #include <smbsrv/smb_fsops.h> -int +smb_sdrc_t smb_com_set_information(struct smb_request *sr) { int rc; @@ -70,34 +70,38 @@ smb_com_set_information(struct smb_request *sr) struct smb_node *node; char *name; + if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { + (void) smbsr_encode_empty_result(sr); + return (SDRC_NORMAL_REPLY); + } + name = kmem_alloc(MAXNAMELEN, KM_SLEEP); if (smbsr_decode_vwv(sr, "wl10.", &dattr, &utime.tv_sec) != 0) { kmem_free(name, MAXNAMELEN); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (smbsr_decode_data(sr, "%S", sr, &path) != 0) { kmem_free(name, MAXNAMELEN); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } utime.tv_nsec = 0; - if ((rc = smb_pathname_reduce(sr, sr->user_cr, path, - sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dir_node, name)) - != 0) { + rc = smb_pathname_reduce(sr, sr->user_cr, path, + sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dir_node, name); + if (rc != 0) { kmem_free(name, MAXNAMELEN); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - if ((rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, - sr->tid_tree->t_snode, dir_node, name, &node, &attr, 0, 0)) != 0) { + rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, + sr->tid_tree->t_snode, dir_node, name, &node, &attr, 0, 0); + if (rc != 0) { smb_node_release(dir_node); kmem_free(name, MAXNAMELEN); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } smb_node_release(dir_node); @@ -116,13 +120,13 @@ smb_com_set_information(struct smb_request *sr) rc = smb_sync_fsattr(sr, sr->user_cr, node); smb_node_release(node); + kmem_free(name, MAXNAMELEN); + if (rc) { - kmem_free(name, MAXNAMELEN); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - smbsr_encode_empty_result(sr); - kmem_free(name, MAXNAMELEN); - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_set_information2.c b/usr/src/uts/common/fs/smbsrv/smb_set_information2.c index 8f00ff66d1..aad9a00871 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_set_information2.c +++ b/usr/src/uts/common/fs/smbsrv/smb_set_information2.c @@ -57,7 +57,7 @@ #include <smbsrv/smb_incl.h> -int +smb_sdrc_t smb_com_set_information2(struct smb_request *sr) { unsigned short la_ddate, la_dtime; @@ -70,22 +70,20 @@ smb_com_set_information2(struct smb_request *sr) rc = smbsr_decode_vwv(sr, "wwwwwww", &sr->smb_fid, &cr_ddate, &cr_dtime, &la_ddate, &la_dtime, &lw_ddate, &lw_dtime); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } node = sr->fid_ofile->f_node; if (node == 0 || sr->fid_ofile->f_ftype != SMB_FTYPE_DISK) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } crtime.tv_nsec = mtime.tv_nsec = atime.tv_nsec = 0; @@ -112,10 +110,9 @@ smb_com_set_information2(struct smb_request *sr) rc = smb_sync_fsattr(sr, sr->user_cr, node); if (rc) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - smbsr_encode_empty_result(sr); - - return (SDRC_NORMAL_REPLY); + rc = smbsr_encode_empty_result(sr); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_create_directory.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_create_directory.c index dc85916d04..d87a87efdd 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_create_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_create_directory.c @@ -58,36 +58,38 @@ #include <smbsrv/smb_incl.h> -extern int smb_common_create_directory(struct smb_request *sr); - - /* * smb_com_trans2_create_directory */ -int +smb_sdrc_t smb_com_trans2_create_directory(struct smb_request *sr, struct smb_xa *xa) { int rc; DWORD status; + if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERROR_ACCESS_DENIED); + return (SDRC_ERROR_REPLY); + } + if (smb_decode_mbc(&xa->req_param_mb, "%4.s", sr, &sr->arg.dirop.fqi.path) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if ((status = smb_validate_dirname(sr->arg.dirop.fqi.path)) != 0) { smbsr_error(sr, status, ERRDOS, ERROR_INVALID_NAME); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if ((rc = smb_common_create_directory(sr)) != 0) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (smb_encode_mbc(&xa->rep_param_mb, "w", 0) < 0) - smbsr_encode_error(sr); + return (SDRC_ERROR_REPLY); return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c index 57b3ba257c..b12e4497e1 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c @@ -290,7 +290,7 @@ smb_unregister_catia_callback() * UCHAR Data[ TotalDataCount ] Level dependent info about the matches * found in the search */ -int +smb_sdrc_t smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa) { int more = 0, rc; @@ -307,20 +307,19 @@ smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa) if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (smb_decode_mbc(&xa->req_param_mb, "%wwww4.u", sr, &sattr, &maxcount, &fflag, &infolev, &path) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } maxdata = smb_trans2_find_get_maxdata(sr, infolev, fflag); if (maxdata == 0) { smbsr_error(sr, NT_STATUS_INVALID_LEVEL, ERRDOS, ERROR_INVALID_LEVEL); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } /* @@ -335,7 +334,8 @@ smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa) if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) (void) smb_convert_unicode_wildcards(path); - (void) smb_rdir_open(sr, path, sattr); + if (smb_rdir_open(sr, path, sattr) != 0) + return (SDRC_ERROR_REPLY); /* * Get a copy of information @@ -362,7 +362,7 @@ smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa) smb_rdir_close(sr); kmem_free(pattern, MAXNAMELEN); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } /* @@ -438,7 +438,7 @@ smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa) * UCHAR Data[TotalDataCount] Level dependent info about the * matches found in the search */ -int +smb_sdrc_t smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa) { uint16_t fflag, infolev; @@ -462,14 +462,13 @@ smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa) */ if (smb_decode_mbc(&xa->req_param_mb, "%www lw", sr, &sr->smb_sid, &maxcount, &infolev, &cookie, &fflag) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); if (sr->sid_odir == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } maxdata = smb_trans2_find_get_maxdata(sr, infolev, fflag); @@ -477,7 +476,7 @@ smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa) smb_rdir_close(sr); smbsr_error(sr, NT_STATUS_INVALID_LEVEL, ERRDOS, ERROR_INVALID_LEVEL); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } /* @@ -511,7 +510,7 @@ smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa) smb_rdir_close(sr); kmem_free(pattern, MAXNAMELEN); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (fflag & SMB_FIND_CLOSE_AFTER_REQUEST || @@ -1096,21 +1095,22 @@ smb_trans2_find_mbc_encode( /* * Close a search started by a Trans2FindFirst2 request. */ -int +smb_sdrc_t smb_com_find_close2(smb_request_t *sr) { - if (smbsr_decode_vwv(sr, "w", &sr->smb_sid) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "w", &sr->smb_sid) != 0) + return (SDRC_ERROR_REPLY); sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); if (sr->sid_odir == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } smb_rdir_close(sr); - smbsr_encode_empty_result(sr); + + if (smbsr_encode_empty_result(sr)) + return (SDRC_ERROR_REPLY); + return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c index d4b5443cd9..6e5f6d1296 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c @@ -73,7 +73,7 @@ uint32_t smb_pad_align(uint32_t offset, uint32_t align); * immediately. */ -int +smb_sdrc_t smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) { static smb_attr_t pipe_attr; @@ -99,14 +99,13 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) if (smb_decode_mbc(&xa->req_param_mb, "ww", &sr->smb_fid, &infolev) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } switch (sr->fid_ofile->f_ftype) { @@ -176,8 +175,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) default: smbsr_error(sr, 0, ERRDOS, ERRbadfile); - /* NOTREACHED */ - break; + return (SDRC_ERROR_REPLY); } filebuf = kmem_alloc(MAXNAMELEN+1, KM_SLEEP); @@ -359,7 +357,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(filebuf, MAXNAMELEN+1); kmem_free(mangled_name, MAXNAMELEN); smbsr_error(sr, 0, ERRDOS, ERRbadfile); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } (void) smb_encode_mbc(&xa->rep_param_mb, "w", 0); if (SMB_IS_STREAM(node)) { @@ -386,8 +384,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(filebuf, MAXNAMELEN+1); kmem_free(mangled_name, MAXNAMELEN); smbsr_error(sr, 0, ERRDOS, ERRunknownlevel); - /* NOTREACHED */ - break; + return (SDRC_ERROR_REPLY); } kmem_free(filebuf, MAXNAMELEN+1); diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c index a1820b899e..721ea1e1ad 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c @@ -261,7 +261,7 @@ is_dot_or_dotdot(char *name) /* * smb_com_trans2_query_fs_information */ -int +smb_sdrc_t smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa) { int rc; @@ -276,22 +276,25 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa) char *fsname = "NTFS"; fsvol_attr_t vol_attr; - if (smb_decode_mbc(&xa->req_param_mb, "w", &infolev) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ + if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); + return (SDRC_ERROR_REPLY); } + if (smb_decode_mbc(&xa->req_param_mb, "w", &infolev) != 0) + return (SDRC_ERROR_REPLY); + snode = sr->tid_tree->t_snode; if (fsd_getattr(&sr->tid_tree->t_fsd, &vol_attr) != 0) { smbsr_errno(sr, ESTALE); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } switch (infolev) { case SMB_INFO_ALLOCATION: if ((rc = smb_fsop_statfs(sr->user_cr, snode, &df)) != 0) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } max_int = (uint64_t)UINT_MAX; @@ -366,7 +369,7 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa) case SMB_QUERY_FS_SIZE_INFO: if ((rc = smb_fsop_statfs(sr->user_cr, snode, &df)) != 0) { smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } length = 512; @@ -388,7 +391,6 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa) break; case SMB_QUERY_FS_ATTRIBUTE_INFO: - if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) || (sr->session->native_os == NATIVE_OS_WINNT) || (sr->session->native_os == NATIVE_OS_WIN2000) || @@ -426,8 +428,7 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa) default: smbsr_error(sr, 0, ERRDOS, ERRunknownlevel); - /* NOTREACHED */ - break; + return (SDRC_ERROR_REPLY); } return (SDRC_NORMAL_REPLY); diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c index bea67e6545..f06fa79d23 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c @@ -324,7 +324,7 @@ /* * Function: int smb_com_trans2_query_path_information(struct smb_request *) */ -int +smb_sdrc_t smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) { char *path, *alt_nm_ptr; @@ -343,7 +343,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } name = kmem_alloc(MAXNAMELEN, KM_SLEEP); @@ -355,8 +355,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(name, MAXNAMELEN); kmem_free(short_name, MAXNAMELEN); kmem_free(name83, MAXNAMELEN); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } /* @@ -383,7 +382,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(short_name, MAXNAMELEN); kmem_free(name83, MAXNAMELEN); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if ((rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, @@ -394,7 +393,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(short_name, MAXNAMELEN); kmem_free(name83, MAXNAMELEN); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } smb_node_release(dir_node); (void) strcpy(name, node->od_name); @@ -577,9 +576,9 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(short_name, MAXNAMELEN); kmem_free(name83, MAXNAMELEN); smbsr_error(sr, 0, ERRDOS, ERRunknownlevel); - /* NOTREACHED */ - break; + return (SDRC_ERROR_REPLY); } + smb_node_release(node); kmem_free(name, MAXNAMELEN); kmem_free(short_name, MAXNAMELEN); diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_file_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_file_information.c index de71abb6d3..cd315c64cc 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_file_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_file_information.c @@ -101,7 +101,7 @@ /* * smb_com_trans2_set_file_information */ -int +smb_sdrc_t smb_com_trans2_set_file_information(struct smb_request *sr, struct smb_xa *xa) { smb_trans2_setinfo_t *info; @@ -116,8 +116,7 @@ smb_com_trans2_set_file_information(struct smb_request *sr, struct smb_xa *xa) &info->level); if (rc != 0) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (!STYPE_ISDSK(sr->tid_tree->t_res_type) || @@ -125,14 +124,14 @@ smb_com_trans2_set_file_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(info, sizeof (smb_trans2_setinfo_t)); smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } info->node = sr->fid_ofile->f_node; @@ -143,19 +142,19 @@ smb_com_trans2_set_file_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(info, sizeof (smb_trans2_setinfo_t)); smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } status = smb_trans2_set_information(sr, info, &smberr); - if (status == NT_STATUS_DATA_ERROR) { - kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_decode_error(sr); - /* NOTREACHED */ - } else if (status == NT_STATUS_UNSUCCESSFUL) { - kmem_free(info, sizeof (smb_trans2_setinfo_t)); + kmem_free(info, sizeof (smb_trans2_setinfo_t)); + + if (status == NT_STATUS_DATA_ERROR) + return (SDRC_ERROR_REPLY); + + if (status == NT_STATUS_UNSUCCESSFUL) { smbsr_error(sr, smberr.status, smberr.errcls, smberr.errcode); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - kmem_free(info, sizeof (smb_trans2_setinfo_t)); + return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c index 782e42f36d..d20de1225e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c @@ -97,12 +97,13 @@ smb_trans2_set_information( return (smb_set_alloc_info(sr, info, smberr)); default: - smberr->status = NT_STATUS_INVALID_INFO_CLASS; - smberr->errcls = ERRDOS; - smberr->errcode = ERROR_INVALID_PARAMETER; - return (NT_STATUS_UNSUCCESSFUL); + break; } - /*NOTREACHED*/ + + smberr->status = NT_STATUS_INVALID_INFO_CLASS; + smberr->errcls = ERRDOS; + smberr->errcode = ERROR_INVALID_PARAMETER; + return (NT_STATUS_UNSUCCESSFUL); } /* diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c index fd3c2d571f..774793821e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c @@ -110,7 +110,7 @@ #include <smbsrv/smb_incl.h> #include <smbsrv/smb_fsops.h> -int +smb_sdrc_t smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) { smb_trans2_setinfo_t *info; @@ -127,8 +127,7 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) if (smb_decode_mbc(&xa->req_param_mb, "%w4.u", sr, &info->level, &info->path) != 0) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (!STYPE_ISDSK(sr->tid_tree->t_res_type) || @@ -136,7 +135,7 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(info, sizeof (smb_trans2_setinfo_t)); smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } rc = smb_pathname_reduce(sr, sr->user_cr, info->path, @@ -146,7 +145,7 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) if (rc != 0) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, @@ -158,21 +157,22 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) if (rc != 0) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); smbsr_errno(sr, rc); + return (SDRC_ERROR_REPLY); } info->node = ret_snode; status = smb_trans2_set_information(sr, info, &smberr); info->node = NULL; smb_node_release(ret_snode); - if (status == NT_STATUS_DATA_ERROR) { - kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_decode_error(sr); - /* NOTREACHED */ - } else if (status == NT_STATUS_UNSUCCESSFUL) { - kmem_free(info, sizeof (smb_trans2_setinfo_t)); + kmem_free(info, sizeof (smb_trans2_setinfo_t)); + + if (status == NT_STATUS_DATA_ERROR) + return (SDRC_ERROR_REPLY); + + if (status == NT_STATUS_UNSUCCESSFUL) { smbsr_error(sr, smberr.status, smberr.errcls, smberr.errcode); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - kmem_free(info, sizeof (smb_trans2_setinfo_t)); + return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c b/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c index 9f8d15807e..1899163654 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c +++ b/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -67,41 +67,37 @@ #include <smbsrv/smb_incl.h> -int +/* + * If the negotiated dialect is MICROSOFT NETWORKS 1.03 or earlier, + * MaxBufferSize in the response message indicates the maximum size + * message that the server can handle. The client should not generate + * messages, nor expect to receive responses, larger than this. This + * must be constant for a given server. For newer dialects, this field + * is ignored. + */ +smb_sdrc_t smb_com_tree_connect(struct smb_request *sr) { + int rc; + /* - * I'm not sure it this should be "%A.sA" - * now that unicode is enabled. + * Perhaps this should be "%A.sA" now that unicode is enabled. */ - if (smbsr_decode_data(sr, "%AAA", sr, &sr->arg.tcon.path, - &sr->arg.tcon.password, &sr->arg.tcon.service) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + rc = smbsr_decode_data(sr, "%AAA", sr, &sr->arg.tcon.path, + &sr->arg.tcon.password, &sr->arg.tcon.service); + if (rc != 0) + return (SDRC_ERROR_REPLY); sr->arg.tcon.flags = 0; - /* - * If the negotiated dialect is MICROSOFT NETWORKS 1.03 - * or earlier, MaxBufferSize in the response message - * indicates the maximum size message that the server can - * handle. The client should not generate messages, nor - * expect to receive responses, larger than this. This - * must be constant for a given server. For newer dialects, - * this field is ignored. - * - * The reason for this is that the maximum buffer size is - * established during the NEGOTIATE. - */ - - (void) smbsr_connect_tree(sr); + if (smbsr_connect_tree(sr) != 0) + return (SDRC_ERROR_REPLY); - smbsr_encode_result(sr, 2, 0, "bwww", + rc = smbsr_encode_result(sr, 2, 0, "bwww", 2, /* wct */ (WORD)smb_maxbufsize, /* MaxBufferSize */ sr->smb_tid, /* TID */ 0); /* bcc */ - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree_connect_andx.c b/usr/src/uts/common/fs/smbsrv/smb_tree_connect_andx.c index 436ecf906c..d805dace1d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_tree_connect_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_tree_connect_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -159,7 +159,7 @@ #include <smbsrv/smb_incl.h> -int +smb_sdrc_t smb_com_tree_connect_andx(struct smb_request *sr) { unsigned char *pwbuf = NULL; @@ -168,10 +168,8 @@ smb_com_tree_connect_andx(struct smb_request *sr) rc = smbsr_decode_vwv(sr, "b.www", &sr->andx_com, &sr->andx_off, &sr->arg.tcon.flags, &pwlen); - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); if (pwlen != 0) { pwbuf = (unsigned char *)smbsr_malloc(&sr->request_storage, @@ -179,19 +177,19 @@ smb_com_tree_connect_andx(struct smb_request *sr) bzero(pwbuf, pwlen); } - if (smbsr_decode_data(sr, "%#cus", sr, pwlen, pwbuf, - &sr->arg.tcon.path, &sr->arg.tcon.service) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + rc = smbsr_decode_data(sr, "%#cus", sr, pwlen, pwbuf, + &sr->arg.tcon.path, &sr->arg.tcon.service); + if (rc != 0) + return (SDRC_ERROR_REPLY); sr->arg.tcon.pwdlen = pwlen; sr->arg.tcon.password = (char *)pwbuf; - (void) smbsr_connect_tree(sr); + if (smbsr_connect_tree(sr) != 0) + return (SDRC_ERROR_REPLY); if (sr->session->dialect < NT_LM_0_12) { - smbsr_encode_result(sr, 2, VAR_BCC, "bb.wwss", + rc = smbsr_encode_result(sr, 2, VAR_BCC, "bb.wwss", (char)2, /* wct */ sr->andx_com, VAR_BCC, @@ -199,7 +197,7 @@ smb_com_tree_connect_andx(struct smb_request *sr) sr->arg.tcon.service, sr->tid_tree->t_typename); } else { - smbsr_encode_result(sr, 3, VAR_BCC, "bb.wwws%u", + rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.wwws%u", (char)3, /* wct */ sr->andx_com, (short)64, @@ -209,5 +207,6 @@ smb_com_tree_connect_andx(struct smb_request *sr) sr, sr->tid_tree->t_typename); } - return (SDRC_NORMAL_REPLY); + + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree_disconnect.c b/usr/src/uts/common/fs/smbsrv/smb_tree_disconnect.c index 560c1d7b76..83efa87ba4 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_tree_disconnect.c +++ b/usr/src/uts/common/fs/smbsrv/smb_tree_disconnect.c @@ -74,7 +74,7 @@ * For the time being, we will leave it till we have time. */ -int +smb_sdrc_t smb_com_tree_disconnect(struct smb_request *sr) { /* @@ -101,11 +101,14 @@ smb_com_tree_disconnect(struct smb_request *sr) if (sr->uid_user == NULL || sr->tid_tree == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } smbsr_rq_notify(sr, sr->session, sr->tid_tree); smb_tree_disconnect(sr->tid_tree); - smbsr_encode_empty_result(sr); + + if (smbsr_encode_empty_result(sr)) + return (SDRC_ERROR_REPLY); + return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c index 8e75fadc36..58a7c93a19 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c +++ b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c @@ -55,22 +55,20 @@ #include <smbsrv/smb_incl.h> -int +smb_sdrc_t smb_com_unlock_byte_range(struct smb_request *sr) { uint32_t Length; uint32_t Offset; DWORD result; - if (smbsr_decode_vwv(sr, "wll", &sr->smb_fid, &Length, &Offset) != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (smbsr_decode_vwv(sr, "wll", &sr->smb_fid, &Length, &Offset) != 0) + return (SDRC_ERROR_REPLY); sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } result = smb_unlock_range(sr, sr->fid_ofile->f_node, @@ -78,10 +76,11 @@ smb_com_unlock_byte_range(struct smb_request *sr) if (result != NT_STATUS_SUCCESS) { smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, ERRDOS, ERRnotlocked); - /* NOT REACHED */ + return (SDRC_ERROR_REPLY); } - smbsr_encode_empty_result(sr); + if (smbsr_encode_empty_result(sr)) + return (SDRC_ERROR_REPLY); return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_vops.c b/usr/src/uts/common/fs/smbsrv/smb_vops.c index a7056d5f3a..db3dd3a1c0 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_vops.c +++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c @@ -351,12 +351,21 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, /* * smb_vop_setattr() * - * smb_fsop_setattr()/smb_vop_setattr() should always be called from the CIFS - * service to set attributes due to special processing for streams files. + * smb_fsop_setattr()/smb_vop_setattr() should always be used instead of + * VOP_SETATTR() when calling from the CIFS service, due to special processing + * for streams files. * - * When smb_vop_setattr() is called on a named stream file, all indicated - * attributes except the size are set on the unnamed stream file. The size - * (if indicated) is set on the named stream file. + * Streams have a size but otherwise do not have separate attributes from + * the (unnamed stream) file, i.e., the security and ownership of the file + * applies to the stream. In contrast, extended attribute files, which are + * used to implement streams, are independent objects with their own + * attributes. + * + * For compatibility with streams, we set the size on the extended attribute + * file and apply other attributes to the (unnamed stream) file. The one + * exception is that the UID and GID can be set on the stream by passing a + * NULL unnamed_vp, which allows callers to synchronize stream ownership + * with the (unnamed stream) file. */ int @@ -403,7 +412,8 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, /* * If the size of the stream needs to be set, set it on * the stream file directly. (All other indicated attributes - * are set on the stream's unnamed stream, above.) + * are set on the stream's unnamed stream, except under the + * exception described in the function header.) */ if (at_size) { diff --git a/usr/src/uts/common/fs/smbsrv/smb_write.c b/usr/src/uts/common/fs/smbsrv/smb_write.c index 79a0ed82ec..fdf78eb8e3 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_write.c +++ b/usr/src/uts/common/fs/smbsrv/smb_write.c @@ -44,9 +44,9 @@ typedef struct smb_write_param { } smb_write_param_t; -int smb_write_common(struct smb_request *sr, smb_write_param_t *param); -int smb_write_truncate(struct smb_request *sr, smb_write_param_t *param); -int smb_set_file_size(struct smb_request *sr); +static int smb_write_common(struct smb_request *, smb_write_param_t *); +static int smb_write_truncate(struct smb_request *, smb_write_param_t *); +int smb_set_file_size(struct smb_request *); /* @@ -59,7 +59,7 @@ int smb_set_file_size(struct smb_request *sr); * counts differ but there is no error, the client will assume that the * server encountered a resource issue. */ -int +smb_sdrc_t smb_com_write(struct smb_request *sr) { smb_write_param_t *param; @@ -71,15 +71,14 @@ smb_com_write(struct smb_request *sr) rc = smbsr_decode_vwv(sr, "wwl", &sr->smb_fid, ¶m->w_count, &off); if (rc != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(param, sizeof (smb_write_param_t)); smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } param->w_offset = (uint64_t)off; @@ -92,8 +91,7 @@ smb_com_write(struct smb_request *sr) if ((rc != 0) || (param->w_vdb.len != param->w_count)) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; @@ -104,12 +102,12 @@ smb_com_write(struct smb_request *sr) if (rc != 0) { kmem_free(param, sizeof (smb_write_param_t)); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - smbsr_encode_result(sr, 1, 0, "bww", 1, param->w_count, 0); + rc = smbsr_encode_result(sr, 1, 0, "bww", 1, param->w_count, 0); kmem_free(param, sizeof (smb_write_param_t)); - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } /* @@ -123,7 +121,7 @@ smb_com_write(struct smb_request *sr) * the mtime. Otherwise the file system stamps the mtime. Failure to * set mtime should not result in an error response. */ -int +smb_sdrc_t smb_com_write_and_close(struct smb_request *sr) { smb_write_param_t *param; @@ -143,15 +141,14 @@ smb_com_write_and_close(struct smb_request *sr) if (rc != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(param, sizeof (smb_write_param_t)); smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } param->w_offset = (uint64_t)off; @@ -167,8 +164,7 @@ smb_com_write_and_close(struct smb_request *sr) if ((rc != 0) || (param->w_vdb.len != param->w_count)) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; @@ -179,18 +175,18 @@ smb_com_write_and_close(struct smb_request *sr) if (rc != 0) { kmem_free(param, sizeof (smb_write_param_t)); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if ((rc = smb_common_close(sr, last_write)) != 0) { kmem_free(param, sizeof (smb_write_param_t)); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - smbsr_encode_result(sr, 1, 0, "bww", 1, param->w_count, 0); + rc = smbsr_encode_result(sr, 1, 0, "bww", 1, param->w_count, 0); kmem_free(param, sizeof (smb_write_param_t)); - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } /* @@ -207,7 +203,7 @@ smb_com_write_and_close(struct smb_request *sr) * counts differ but there is no error, the client will assume that the * server encountered a resource issue. */ -int +smb_sdrc_t smb_com_write_and_unlock(struct smb_request *sr) { smb_write_param_t *param; @@ -218,7 +214,7 @@ smb_com_write_and_unlock(struct smb_request *sr) if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } param = kmem_zalloc(sizeof (smb_write_param_t), KM_SLEEP); @@ -227,28 +223,26 @@ smb_com_write_and_unlock(struct smb_request *sr) &remcnt); if (rc != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(param, sizeof (smb_write_param_t)); smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (param->w_count == 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ + kmem_free(param, sizeof (smb_write_param_t)); + return (SDRC_ERROR_REPLY); } rc = smbsr_decode_data(sr, "D", ¶m->w_vdb); if ((rc != 0) || (param->w_count != param->w_vdb.len)) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } param->w_offset = (uint64_t)off; @@ -257,7 +251,7 @@ smb_com_write_and_unlock(struct smb_request *sr) if ((rc = smb_write_common(sr, param)) != 0) { kmem_free(param, sizeof (smb_write_param_t)); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } result = smb_unlock_range(sr, sr->fid_ofile->f_node, param->w_offset, @@ -266,12 +260,12 @@ smb_com_write_and_unlock(struct smb_request *sr) kmem_free(param, sizeof (smb_write_param_t)); smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, ERRDOS, ERRnotlocked); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } - smbsr_encode_result(sr, 1, 0, "bww", 1, param->w_count, 0); + rc = smbsr_encode_result(sr, 1, 0, "bww", 1, param->w_count, 0); kmem_free(param, sizeof (smb_write_param_t)); - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } /* @@ -285,7 +279,7 @@ smb_com_write_and_unlock(struct smb_request *sr) * If bit 0 of WriteMode is set, Fid must refer to a disk file and * the data must be on stable storage before responding. */ -int +smb_sdrc_t smb_com_write_andx(struct smb_request *sr) { smb_write_param_t *param; @@ -315,30 +309,28 @@ smb_com_write_andx(struct smb_request *sr) if (rc != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(param, sizeof (smb_write_param_t)); smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } if (SMB_WRMODE_IS_STABLE(param->w_mode) && STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { kmem_free(param, sizeof (smb_write_param_t)); smbsr_error(sr, 0, ERRSRV, ERRaccess); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } rc = smbsr_decode_data(sr, "#.#B", data_offset, param->w_count, ¶m->w_vdb); if ((rc != 0) || (param->w_vdb.len != param->w_count)) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; @@ -347,15 +339,15 @@ smb_com_write_andx(struct smb_request *sr) if ((rc = smb_write_common(sr, param)) != 0) { kmem_free(param, sizeof (smb_write_param_t)); smbsr_errno(sr, rc); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } } - smbsr_encode_result(sr, 6, 0, "bb1.ww6.w", + rc = smbsr_encode_result(sr, 6, 0, "bb1.ww6.w", 6, sr->andx_com, 15, param->w_count, 0); kmem_free(param, sizeof (smb_write_param_t)); - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } /* @@ -363,7 +355,7 @@ smb_com_write_andx(struct smb_request *sr) * * Returns errno values. */ -int +static int smb_write_common(struct smb_request *sr, smb_write_param_t *param) { struct smb_ofile *ofile = sr->fid_ofile; @@ -379,10 +371,8 @@ smb_write_common(struct smb_request *sr, smb_write_param_t *param) if (node->attr.sa_vattr.va_type != VDIR) { rc = smb_lock_range_access(sr, node, param->w_offset, param->w_count, B_TRUE); - if (rc != NT_STATUS_SUCCESS) { - smbsr_error(sr, rc, ERRSRV, ERRaccess); - /* NOTREACHED */ - } + if (rc != NT_STATUS_SUCCESS) + return (EPERM); } if (SMB_WRMODE_IS_STABLE(param->w_mode) || @@ -435,46 +425,41 @@ smb_write_common(struct smb_request *sr, smb_write_param_t *param) * * Returns errno values. */ -int +static int smb_write_truncate(struct smb_request *sr, smb_write_param_t *param) { struct smb_ofile *ofile = sr->fid_ofile; smb_node_t *node = ofile->f_node; boolean_t append_only = B_FALSE; + uint32_t status; int rc; if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) return (0); - rc = smb_ofile_access(sr->fid_ofile, sr->user_cr, FILE_WRITE_DATA); - if (rc != NT_STATUS_SUCCESS) { - rc = smb_ofile_access(sr->fid_ofile, sr->user_cr, + status = smb_ofile_access(sr->fid_ofile, sr->user_cr, FILE_WRITE_DATA); + if (status != NT_STATUS_SUCCESS) { + status = smb_ofile_access(sr->fid_ofile, sr->user_cr, FILE_APPEND_DATA); - if (rc != NT_STATUS_SUCCESS) { - smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, - ERROR_ACCESS_DENIED); - /* NOTREACHED */ - } else { + if (status != NT_STATUS_SUCCESS) + return (EACCES); + else append_only = B_TRUE; - } } smb_rwx_xenter(&node->n_lock); if (append_only && (param->w_offset < node->n_size)) { smb_rwx_xexit(&node->n_lock); - smbsr_error(sr, NT_STATUS_ACCESS_DENIED, - ERRDOS, ERRnoaccess); - /* NOTREACHED */ + return (EACCES); } if (node->attr.sa_vattr.va_type != VDIR) { - rc = smb_lock_range_access(sr, node, param->w_offset, + status = smb_lock_range_access(sr, node, param->w_offset, param->w_count, B_TRUE); - if (rc != NT_STATUS_SUCCESS) { + if (status != NT_STATUS_SUCCESS) { smb_rwx_xexit(&node->n_lock); - smbsr_error(sr, rc, ERRSRV, ERRaccess); - /* NOTREACHED */ + return (EACCES); } } @@ -546,12 +531,10 @@ smb_set_file_size(struct smb_request *sr) * We never send raw write commands to other servers so, if we receive a * write_complete, we treat it as an error. */ -int +smb_sdrc_t /*ARGSUSED*/ smb_com_write_complete(struct smb_request *sr) { - smbsr_decode_error(sr); - /* NOT REACHED */ - return (0); + return (SDRC_ERROR_REPLY); } /* @@ -562,13 +545,13 @@ smb_com_write_complete(struct smb_request *sr) * connection oriented transports and NT supports SMB_COM_READ_MPX * only over connectionless transports. */ -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_write_mpx(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); } -int /*ARGSUSED*/ +smb_sdrc_t /*ARGSUSED*/ smb_com_write_mpx_secondary(struct smb_request *sr) { return (SDRC_UNIMPLEMENTED); diff --git a/usr/src/uts/common/fs/smbsrv/smb_write_raw.c b/usr/src/uts/common/fs/smbsrv/smb_write_raw.c index 4c7fcb6f81..90d32ab442 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_write_raw.c +++ b/usr/src/uts/common/fs/smbsrv/smb_write_raw.c @@ -199,7 +199,7 @@ static int smb_transfer_write_raw_data(smb_request_t *sr, #define WR_MODE_WR_THRU 1 -int +smb_sdrc_t smb_com_write_raw(struct smb_request *sr) { int rc = 0; @@ -218,9 +218,8 @@ smb_com_write_raw(struct smb_request *sr) smb_node_t *fnode; smb_error_t err; - if (sr->session->s_state != SMB_SESSION_STATE_WRITE_RAW_ACTIVE) { + if (sr->session->s_state != SMB_SESSION_STATE_WRITE_RAW_ACTIVE) return (SDRC_DROP_VC); - } if (sr->smb_wct == 12) { off_high = 0; @@ -235,10 +234,8 @@ smb_com_write_raw(struct smb_request *sr) data_offset -= 63; } - if (rc != 0) { - smbsr_decode_error(sr); - /* NOTREACHED */ - } + if (rc != 0) + return (SDRC_ERROR_REPLY); off = ((offset_t)off_high << 32) | off_low; addl_xfer_count = count - data_length; @@ -246,7 +243,7 @@ smb_com_write_raw(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } fnode = sr->fid_ofile->f_node; @@ -263,7 +260,7 @@ smb_com_write_raw(struct smb_request *sr) count, B_TRUE); if (rc != NT_STATUS_SUCCESS) { smbsr_error(sr, rc, ERRSRV, ERRaccess); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } } } @@ -275,8 +272,7 @@ smb_com_write_raw(struct smb_request *sr) if (sr->smb_data.chain_offset + data_offset + data_length > sr->smb_data.max_bytes) { /* Error handling code will wake up the session daemon */ - smbsr_decode_error(sr); - /* NOTREACHED */ + return (SDRC_ERROR_REPLY); } /* @@ -451,9 +447,9 @@ notify_write_raw_complete: } /* Write complete notification */ sr->first_smb_com = SMB_COM_WRITE_COMPLETE; - smbsr_encode_result(sr, 1, 0, "bww", 1, + rc = smbsr_encode_result(sr, 1, 0, "bww", 1, count - (lcount + addl_lcount), 0); - return (SDRC_NORMAL_REPLY); + return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY); } diff --git a/usr/src/uts/common/smbsrv/cifs.h b/usr/src/uts/common/smbsrv/cifs.h index 1f657a2d8c..0734a60727 100644 --- a/usr/src/uts/common/smbsrv/cifs.h +++ b/usr/src/uts/common/smbsrv/cifs.h @@ -834,7 +834,7 @@ extern "C" { #define SV_LOCAL_LIST_ONLY 0x40000000 /* Enumerate only "local" */ #define SV_TYPE_DOMAIN_ENUM 0x80000000 /* Enumerate Domains */ -#define MY_SERVER_TYPE (SV_SERVER | SV_NT | SV_SERVER_NT | SV_DOMAIN_MEMBER) +#define MY_SERVER_TYPE (SV_SERVER | SV_NT | SV_SERVER_NT) #define PRQ_ACTIVE 0 /* Active */ diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h index 264e9c5a76..135c2b942e 100644 --- a/usr/src/uts/common/smbsrv/smb_kproto.h +++ b/usr/src/uts/common/smbsrv/smb_kproto.h @@ -74,6 +74,108 @@ int smb_service_start_threads(struct smb_info *si); void smb_service_stop_threads(struct smb_info *si); /* + * SMB request handers called from the dispatcher. + */ +smb_sdrc_t smb_com_cancel_forward(struct smb_request *); +smb_sdrc_t smb_com_check_directory(struct smb_request *); +smb_sdrc_t smb_com_close(struct smb_request *); +smb_sdrc_t smb_com_close_and_tree_disconnect(struct smb_request *); +smb_sdrc_t smb_com_close_print_file(struct smb_request *); +smb_sdrc_t smb_com_copy(struct smb_request *); +smb_sdrc_t smb_com_create(struct smb_request *); +smb_sdrc_t smb_com_create_directory(struct smb_request *); +smb_sdrc_t smb_com_create_new(struct smb_request *); +smb_sdrc_t smb_com_create_temporary(struct smb_request *); +smb_sdrc_t smb_com_delete(struct smb_request *); +smb_sdrc_t smb_com_delete_directory(struct smb_request *); +smb_sdrc_t smb_com_echo(struct smb_request *); +smb_sdrc_t smb_com_find(struct smb_request *); +smb_sdrc_t smb_com_find_close(struct smb_request *); +smb_sdrc_t smb_com_find_close2(struct smb_request *); +smb_sdrc_t smb_com_find_notify_close(struct smb_request *); +smb_sdrc_t smb_com_find_unique(struct smb_request *); +smb_sdrc_t smb_com_flush(struct smb_request *); +smb_sdrc_t smb_com_forward_user_name(struct smb_request *); +smb_sdrc_t smb_com_get_machine_name(struct smb_request *); +smb_sdrc_t smb_com_get_print_queue(struct smb_request *); +smb_sdrc_t smb_com_invalid_command(struct smb_request *); +smb_sdrc_t smb_com_ioctl(struct smb_request *); +smb_sdrc_t smb_com_ioctl_secondary(struct smb_request *); +smb_sdrc_t smb_com_lock_and_read(struct smb_request *); +smb_sdrc_t smb_com_lock_byte_range(struct smb_request *); +smb_sdrc_t smb_com_locking_andx(struct smb_request *); +smb_sdrc_t smb_com_logoff_andx(struct smb_request *); +smb_sdrc_t smb_com_move(struct smb_request *); +smb_sdrc_t smb_com_negotiate(struct smb_request *); +smb_sdrc_t smb_com_nt_cancel(struct smb_request *); +smb_sdrc_t smb_com_nt_create_andx(struct smb_request *); +smb_sdrc_t smb_com_nt_transact(struct smb_request *); +smb_sdrc_t smb_com_nt_transact_secondary(struct smb_request *); +smb_sdrc_t smb_com_open(struct smb_request *); +smb_sdrc_t smb_com_open_andx(struct smb_request *); +smb_sdrc_t smb_com_open_print_file(struct smb_request *); +smb_sdrc_t smb_com_process_exit(struct smb_request *); +smb_sdrc_t smb_com_query_information(struct smb_request *); +smb_sdrc_t smb_com_query_information2(struct smb_request *); +smb_sdrc_t smb_com_query_information_disk(struct smb_request *); +smb_sdrc_t smb_com_read(struct smb_request *); +smb_sdrc_t smb_com_read_andx(struct smb_request *); +smb_sdrc_t smb_com_read_mpx(struct smb_request *); +smb_sdrc_t smb_com_read_mpx_secondary(struct smb_request *); +smb_sdrc_t smb_com_read_raw(struct smb_request *); +smb_sdrc_t smb_com_rename(struct smb_request *); +smb_sdrc_t smb_com_search(struct smb_request *); +smb_sdrc_t smb_com_seek(struct smb_request *); +smb_sdrc_t smb_com_send_broadcast_message(struct smb_request *); +smb_sdrc_t smb_com_send_end_mb_message(struct smb_request *); +smb_sdrc_t smb_com_send_single_message(struct smb_request *); +smb_sdrc_t smb_com_send_start_mb_message(struct smb_request *); +smb_sdrc_t smb_com_send_text_mb_message(struct smb_request *); +smb_sdrc_t smb_com_session_setup_andx(struct smb_request *); +smb_sdrc_t smb_com_set_information(struct smb_request *); +smb_sdrc_t smb_com_set_information2(struct smb_request *); +smb_sdrc_t smb_com_transaction(struct smb_request *); +smb_sdrc_t smb_com_transaction2(struct smb_request *); +smb_sdrc_t smb_com_transaction2_secondary(struct smb_request *); +smb_sdrc_t smb_com_transaction_secondary(struct smb_request *); +smb_sdrc_t smb_com_tree_connect(struct smb_request *); +smb_sdrc_t smb_com_tree_connect_andx(struct smb_request *); +smb_sdrc_t smb_com_tree_disconnect(struct smb_request *); +smb_sdrc_t smb_com_unlock_byte_range(struct smb_request *); +smb_sdrc_t smb_com_write(struct smb_request *); +smb_sdrc_t smb_com_write_and_close(struct smb_request *); +smb_sdrc_t smb_com_write_and_unlock(struct smb_request *); +smb_sdrc_t smb_com_write_andx(struct smb_request *); +smb_sdrc_t smb_com_write_complete(struct smb_request *); +smb_sdrc_t smb_com_write_mpx(struct smb_request *); +smb_sdrc_t smb_com_write_mpx_secondary(struct smb_request *); +smb_sdrc_t smb_com_write_print_file(struct smb_request *); +smb_sdrc_t smb_com_write_raw(struct smb_request *); + +smb_sdrc_t smb_nt_transact_create(struct smb_request *, struct smb_xa *); +smb_sdrc_t smb_nt_transact_notify_change(struct smb_request *, struct smb_xa *); +smb_sdrc_t smb_nt_transact_query_security_info(struct smb_request *, + struct smb_xa *); +smb_sdrc_t smb_nt_transact_set_security_info(struct smb_request *, + struct smb_xa *); +smb_sdrc_t smb_nt_transact_ioctl(struct smb_request *, struct smb_xa *); + +smb_sdrc_t smb_com_trans2_create_directory(struct smb_request *, + struct smb_xa *); +smb_sdrc_t smb_com_trans2_find_first2(struct smb_request *, struct smb_xa *); +smb_sdrc_t smb_com_trans2_find_next2(struct smb_request *, struct smb_xa *); +smb_sdrc_t smb_com_trans2_query_fs_information(struct smb_request *, + struct smb_xa *); +smb_sdrc_t smb_com_trans2_query_path_information(struct smb_request *, + struct smb_xa *); +smb_sdrc_t smb_com_trans2_query_file_information(struct smb_request *, + struct smb_xa *); +smb_sdrc_t smb_com_trans2_set_path_information(struct smb_request *, + struct smb_xa *); +smb_sdrc_t smb_com_trans2_set_file_information(struct smb_request *, + struct smb_xa *); + +/* * Logging functions */ void smb_log_flush(void); @@ -125,6 +227,8 @@ void smbsr_cleanup(struct smb_request *sr); int smbsr_connect_tree(struct smb_request *); +int smb_common_create_directory(struct smb_request *); + int smb_convert_unicode_wildcards(char *); int smb_ascii_or_unicode_strlen(struct smb_request *, char *); int smb_ascii_or_unicode_strlen_null(struct smb_request *, char *); @@ -136,24 +240,21 @@ int smb_rdir_open(struct smb_request *, char *, unsigned short); int smb_rdir_next(smb_request_t *sr, smb_node_t **rnode, smb_odir_context_t *pc); -DWORD smb_open_subr(struct smb_request *); +uint32_t smb_common_open(smb_request_t *); DWORD smb_validate_object_name(char *path, unsigned int ftype); uint32_t smb_omode_to_amask(uint32_t desired_access); void sshow_distribution_info(char *); -int smb_dispatch_request(struct smb_request *); -void smbsr_disconnect_file(smb_request_t *sr); -void smbsr_disconnect_dir(smb_request_t *sr); -void smbsr_check_result(struct smb_request *, int, int); -void smbsr_decode_error(struct smb_request *); -void smbsr_encode_error(struct smb_request *); -void smbsr_encode_empty_result(struct smb_request *sr); +void smb_dispatch_request(struct smb_request *); +void smbsr_disconnect_file(smb_request_t *); +void smbsr_disconnect_dir(smb_request_t *); +int smbsr_encode_empty_result(struct smb_request *); int smbsr_decode_vwv(struct smb_request *sr, char *fmt, ...); int smbsr_decode_data(struct smb_request *sr, char *fmt, ...); -void smbsr_encode_result(struct smb_request *, int, int, char *, ...); +int smbsr_encode_result(struct smb_request *, int, int, char *, ...); smb_xa_t *smbsr_lookup_xa(smb_request_t *sr); void smbsr_send_reply(struct smb_request *); @@ -212,11 +313,11 @@ int smb_net_txb_send(struct sonode *, smb_txlst_t *, smb_txbuf_t *); /* * SMB RPC interface */ -int smb_rpc_open(struct smb_request *sr); -void smb_rpc_close(struct smb_ofile *of); -int smb_rpc_transact(struct smb_request *sr, struct uio *uio); -int smb_rpc_read(struct smb_request *sr, struct uio *uio); -int smb_rpc_write(struct smb_request *sr, struct uio *uio); +int smb_rpc_open(struct smb_request *); +void smb_rpc_close(struct smb_ofile *); +smb_sdrc_t smb_rpc_transact(struct smb_request *, struct uio *); +int smb_rpc_read(struct smb_request *, struct uio *); +int smb_rpc_write(struct smb_request *, struct uio *); /* * SMB node functions (file smb_node.c) @@ -296,36 +397,13 @@ char *smb_kstrdup(const char *s, size_t n); int smb_sync_fsattr(struct smb_request *sr, cred_t *cr, struct smb_node *node); -int smb_com_create_directory(struct smb_request *sr); DWORD smb_validate_dirname(char *path); -int smb_com_trans2_create_directory(struct smb_request *sr, struct smb_xa *xa); -int smb_com_trans2_find_first2(struct smb_request *sr, struct smb_xa *xa); -int smb_com_trans2_find_next2(struct smb_request *sr, struct smb_xa *xa); -int smb_com_trans2_query_fs_information(struct smb_request *sr, - struct smb_xa *xa); -int smb_com_trans2_query_path_information( - struct smb_request *sr, struct smb_xa *xa); -int smb_com_trans2_query_file_information( - struct smb_request *sr, struct smb_xa *xa); -int smb_com_trans2_set_path_information( - struct smb_request *sr, struct smb_xa *xa); -int smb_com_trans2_set_file_information( - struct smb_request *sr, struct smb_xa *xa); void smb_encode_stream_info(struct smb_request *sr, struct smb_xa *xa, smb_node_t *snode, smb_attr_t *attr); -int smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa); -int smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa); -int smb_nt_transact_query_security_info(struct smb_request *sr, - struct smb_xa *xa); -int smb_nt_transact_set_security_info(struct smb_request *sr, - struct smb_xa *xa); -int smb_nt_transact_ioctl(struct smb_request *sr, struct smb_xa *xa); - /* NOTIFY CHANGE */ -int smb_reply_notify_change_request(smb_request_t *sr); void smb_process_session_notify_change_queue(struct smb_session *session); void smb_process_node_notify_change_queue(struct smb_node *node); void smb_reply_specific_cancel_request(struct smb_request *sr); diff --git a/usr/src/uts/common/smbsrv/smb_winpipe.h b/usr/src/uts/common/smbsrv/smb_winpipe.h index 22b258ad02..4e4f383543 100755 --- a/usr/src/uts/common/smbsrv/smb_winpipe.h +++ b/usr/src/uts/common/smbsrv/smb_winpipe.h @@ -46,7 +46,7 @@ extern "C" { #define SMB_IO_MAX_SIZE 32 #define SMB_MAX_PIPENAMELEN 32 - +#define SMB_CTXT_PIPE_SZ 65536 #define SMB_WINPIPE_DOOR_DOWN_PATH "/var/run/winpipe_doordown" #define SMB_DOWNCALLINFO_MAGIC 0x19121969 diff --git a/usr/src/uts/common/smbsrv/smbvar.h b/usr/src/uts/common/smbsrv/smbvar.h index 316c10e814..7963922a3e 100644 --- a/usr/src/uts/common/smbsrv/smbvar.h +++ b/usr/src/uts/common/smbsrv/smbvar.h @@ -981,6 +981,12 @@ struct smb_fqi { /* fs_query_info */ #define OPLOCK_MIN_TIMEOUT (5 * 1000) #define OPLOCK_STD_TIMEOUT (15 * 1000) +typedef struct { + uint32_t severity; + uint32_t status; + uint16_t errcls; + uint16_t errcode; +} smb_error_t; /* * SMB Request State Machine @@ -1148,9 +1154,12 @@ struct smb_request { unsigned int reply_seqnum; /* reply sequence number */ unsigned char first_smb_com; /* command code */ unsigned char smb_com; /* command code */ - unsigned char smb_rcls; /* error code class */ - unsigned char smb_reh; /* rsvd (AH DOS INT-24 ERR) */ + + uint8_t smb_rcls; /* error code class */ + uint8_t smb_reh; /* rsvd (AH DOS INT-24 ERR) */ uint16_t smb_err; /* error code */ + smb_error_t smb_error; + uint8_t smb_flg; /* flags */ uint16_t smb_flg2; /* flags */ uint16_t smb_pid_high; /* high part of pid */ @@ -1216,7 +1225,6 @@ struct smb_request { } arg; - label_t exjb; cred_t *user_cr; }; @@ -1301,13 +1309,17 @@ typedef struct smb_xa { #define SDDF_SUPPRESS_UNLEASH 0x0004 #define SDDF_SUPPRESS_SHOW 0x0080 -#define SDRC_NORMAL_REPLY 0 -#define SDRC_DROP_VC 1 -#define SDRC_NO_REPLY 2 -#define SDRC_ERROR_REPLY 3 -#define SDRC_UNIMPLEMENTED 4 -#define SDRC_UNSUPPORTED 5 - +/* + * SMB dispatch return codes. + */ +typedef enum { + SDRC_NORMAL_REPLY = 0, + SDRC_DROP_VC, + SDRC_NO_REPLY, + SDRC_ERROR_REPLY, + SDRC_UNIMPLEMENTED, + SDRC_UNSUPPORTED +} smb_sdrc_t; struct vardata_block { unsigned char tag; @@ -1374,13 +1386,6 @@ typedef struct smb_info { #define SMB_NEW_KID() atomic_inc_64_nv(&smb_info.si_global_kid) #define SMB_UNIQ_FID() atomic_inc_32_nv(&smb_info.si_uniq_fid) -typedef struct { - uint32_t severity; - uint32_t status; - uint16_t errcls; - uint16_t errcode; -} smb_error_t; - /* * This is to be used by Trans2SetFileInfo * and Trans2SetPathInfo @@ -1411,7 +1416,7 @@ typedef struct smb_tsd { #define SMB_INVALID_CRDISPOSITION -1 typedef struct smb_dispatch_table { - int (*sdt_function)(struct smb_request *); + smb_sdrc_t (*sdt_function)(struct smb_request *); char sdt_dialect; unsigned char sdt_flags; krw_t sdt_slock_mode; |