This commit is contained in:
obarthel
2018-12-23 11:47:19 +01:00
10 changed files with 941 additions and 442 deletions
+47
View File
@@ -2725,3 +2725,50 @@ smbfs 2.5 (16.12.2018)
- This version fixes the instant crash in the fully optimized 68k/020+
builds, which was cased by a missing __saveds keyword.
smbfs 2.6 (16.12.2018)
- Added the WRITETHRESHOLD parameter which can be used to disable the
separate transmission of the SMB message header and its payload if
the combined sizes of both are smaller than or equal to the
threshold value. This is intended to improve write performance for
small amounts of data which would otherwise linger in the
transmission queue.
smbfs 2.7 (17.12.2018)
- Added the READTHRESHOLD counterpart to WRITETHRESHOLD which affects
the read operations.
- The smb_receive_raw() function in "sock.c" no longer copies the NetBIOS
header into the receive buffer separately, but makes sure that the
initial receive operation takes care of it.
- The allocate_path_name() function in "smb_abstraction.c" failed to put
the path separator character where it should be, resulting in the path
name and the file/directory name to get lumped together. This affected
creation of files and directories both.
smbfs 2.8 (19.12.2018)
- The default values for READTHRESHOLD and WRITETHRESHOLD now have the
effect of transmitting the SMB header and the payload separately,
just like it was introduces in version 2.1.
Use something like READTHRESHOLD=1500 and WRITETHRESHOLD=1500 to
send packets smaller than or equal to 1500 bytes as a combined
lump of data, and data larger than 1500 bytes as separate SMB
header and payload.
- When processing the share name the limitations on the individual
components (server name, share, port number/IP service name) are
no longer verified using hard-coded lengths, but use the respective
buffer limits instead. The port number/IP service name length
check is new.
- Added more debug log output to the code which now performs the
file and lock name/address lookups instead of walking through
the entire file/lock lists.
+5
View File
@@ -28,6 +28,11 @@ struct smb_server
data blocks */
dword max_raw_size; /* Maximum SMB_COM_WRITE_RAW and
SMB_COM_READ_RAW data. */
dword smb_write_threshold; /* If SMB header + payload size is smaller
than or equal to this threshold, send
both in a single combined send() operation
rather than separately. */
dword smb_read_threshold; /* Same as above, but for recv() operations. */
int max_recv; /* added by CS */
word server_uid;
word tid;
+282 -144
View File
@@ -261,7 +261,7 @@ static ULONG stack_usage_exit(const struct StackSwapStruct * stk);
static LONG CVSPrintf(const TEXT * format_string, APTR args);
static int LocalVSNPrintf(STRPTR buffer, int limit, const TEXT * formatString, APTR args);
static void cleanup(void);
static BOOL setup(const TEXT * program_name, const TEXT * service, const TEXT * workgroup, STRPTR username, STRPTR opt_password, BOOL opt_change_username_case, BOOL opt_change_password_case, const TEXT * opt_clientname, const TEXT * opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, LONG *opt_time_zone_offset, LONG *opt_dst_offset, BOOL opt_raw_smb, BOOL opt_unicode, BOOL opt_prefer_core_protocol, BOOL opt_session_setup_delay_unicode, BOOL opt_write_behind, const TEXT * device_name, const TEXT * volume_name, BOOL add_volume, const TEXT * translation_file);
static BOOL setup(const TEXT * program_name, const TEXT * service, const TEXT * workgroup, STRPTR username, STRPTR opt_password, BOOL opt_change_username_case, BOOL opt_change_password_case, const TEXT * opt_clientname, const TEXT * opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, LONG *opt_time_zone_offset, LONG *opt_dst_offset, BOOL opt_raw_smb, BOOL opt_unicode, BOOL opt_prefer_core_protocol, BOOL opt_session_setup_delay_unicode, BOOL opt_write_behind, int opt_smb_request_write_threshold, int opt_smb_request_read_threshold, const TEXT * device_name, const TEXT * volume_name, BOOL add_volume, const TEXT * translation_file);
static void file_system_handler(BOOL raise_priority, const TEXT * device_name, const TEXT * volume_name, const TEXT * service_name);
/****************************************************************************/
@@ -758,6 +758,8 @@ main(void)
KEY Protocol;
SWITCH NetBIOSTransport;
SWITCH WriteBehind;
NUMBER WriteThreshold;
NUMBER ReadThreshold;
KEY SessionSetup;
KEY Unicode;
SWITCH CP437;
@@ -798,6 +800,8 @@ main(void)
"PROTOCOL/K,"
"NETBIOS/S,"
"WRITEBEHIND/S,"
"WRITETHRESHOLD/N/K,"
"READTHRESHOLD/N/K,"
"SESSIONSETUP/K,"
"UNICODE/K,"
"CP437/S,"
@@ -817,6 +821,8 @@ main(void)
LONG tz_number, dst_number, debug_number;
LONG cache_size = 0;
LONG max_transmit = -1;
LONG smb_write_threshold = 0;
LONG smb_read_threshold = 0;
LONG timeout = 0;
TEXT env_protocol[8];
TEXT env_workgroup_name[17];
@@ -1015,6 +1021,30 @@ main(void)
args.MaxNameLen = &MaxNameLen;
}
str = get_icon_tool_type_value("WRITETHRESHOLD", NULL);
if(str != NULL)
{
if(StrToLong(str,&smb_write_threshold) == -1)
{
report_error("Invalid number '%s' for 'WRITETHRESHOLD' parameter.",str);
goto out;
}
args.WriteThreshold = &smb_write_threshold;
}
str = get_icon_tool_type_value("READTHRESHOLD", NULL);
if(str != NULL)
{
if(StrToLong(str,&smb_read_threshold) == -1)
{
report_error("Invalid number '%s' for 'READTHRESHOLD' parameter.",str);
goto out;
}
args.ReadThreshold = &smb_read_threshold;
}
str = get_icon_tool_type_value("TZ","TIMEZONEOFFSET");
if(str != NULL)
{
@@ -1326,8 +1356,8 @@ main(void)
{
SHOWMSG("using code page 437 translation");
memmove(map_amiga_to_smb_name,unicode_to_cp437,sizeof(unicode_to_cp437));
memmove(map_smb_to_amiga_name,cp437_to_unicode,sizeof(cp437_to_unicode));
memcpy(map_amiga_to_smb_name,unicode_to_cp437,sizeof(unicode_to_cp437));
memcpy(map_smb_to_amiga_name,cp437_to_unicode,sizeof(cp437_to_unicode));
TranslateNames = TRUE;
}
@@ -1335,8 +1365,8 @@ main(void)
{
SHOWMSG("using code page 850 translation");
memmove(map_amiga_to_smb_name,unicode_to_cp850,sizeof(unicode_to_cp850));
memmove(map_smb_to_amiga_name,cp850_to_unicode,sizeof(cp850_to_unicode));
memcpy(map_amiga_to_smb_name,unicode_to_cp850,sizeof(unicode_to_cp850));
memcpy(map_smb_to_amiga_name,cp850_to_unicode,sizeof(cp850_to_unicode));
TranslateNames = TRUE;
}
@@ -1381,6 +1411,16 @@ main(void)
}
}
if(args.WriteThreshold == NULL)
args.WriteThreshold = &smb_write_threshold;
D(("write threshold = %ld", (*args.WriteThreshold)));
if(args.ReadThreshold == NULL)
args.ReadThreshold = &smb_read_threshold;
D(("read threshold = %ld", (*args.ReadThreshold)));
DisableExAll = (BOOL)(args.DisableExAll != 0);
CaseSensitive = (BOOL)(args.CaseSensitive != 0);
OmitHidden = (BOOL)(args.OmitHidden != 0);
@@ -1492,6 +1532,8 @@ main(void)
Stricmp(args.Protocol,"CORE") == SAME,
Stricmp(args.SessionSetup,"DELAY") == SAME,
args.WriteBehind,
(*args.WriteThreshold),
(*args.ReadThreshold),
args.DeviceName,
args.VolumeName,
get_switch_status(args.AddVolume, TRUE),
@@ -2910,41 +2952,71 @@ find_file_node_by_name(const TEXT * name,const struct FileNode * skip)
struct FileNode * result = NULL;
struct FileNode * fn;
#ifndef USE_SPLAY_TREE
ASSERT( name != NULL );
for(fn = (struct FileNode *)FileList.mlh_Head ;
fn->fn_MinNode.mln_Succ != NULL ;
fn = (struct FileNode *)fn->fn_MinNode.mln_Succ)
#ifndef USE_SPLAY_TREE
{
if(fn != skip && compare_names(name,fn->fn_FullName) == SAME)
D(("searching for file with name '%s'", name));
for(fn = (struct FileNode *)FileList.mlh_Head ;
fn->fn_MinNode.mln_Succ != NULL ;
fn = (struct FileNode *)fn->fn_MinNode.mln_Succ)
{
result = fn;
break;
if(fn != skip && compare_names(name,fn->fn_FullName) == SAME)
{
result = fn;
break;
}
}
if(result != NULL)
D(("found it (= 0x%08lx)", result));
else
D(("didn't find it"));
}
#else
{
struct splay_node * sn;
D(("looking up file with name '%s'", name));
/* Find the list of all files which match the given name. */
sn = splay_tree_find(&FileNameTree, (splay_key_t)name);
if(sn != NULL)
{
fn = (struct FileNode *)sn->sn_userdata;
ASSERT( fn != NULL );
/* Use this entry, unless it's the one which we
* wanted to skip.
*/
if (fn != skip)
{
result = fn;
D(("found it (= 0x%08lx)", result));
}
/* Use the next entry in the list, if possible. */
else if (sn->sn_next != NULL)
{
result = (struct FileNode *)sn->sn_next->sn_userdata;
D(("found it, but can't use it, so using the next best entry (= 0x%08lx)", result));
if(result == NULL)
D(("...but didn't actually find it"));
}
else
{
D(("didn't find it"));
}
}
else
{
D(("didn't find it"));
}
}
#else
struct splay_node * sn;
/* Find the list of all files which match the given name. */
sn = splay_tree_find(&FileNameTree, (splay_key_t)name);
if(sn != NULL)
{
fn = (struct FileNode *)sn->sn_userdata;
ASSERT( fn != NULL );
/* Use this entry, unless it's the one which we
* wanted to skip.
*/
if (fn != skip)
result = fn;
/* Use the next entry in the list, if possible. */
else if (sn->sn_next != NULL)
result = (struct FileNode *)sn->sn_next->sn_userdata;
}
#endif /* USE_SPLAY_TREE */
return(result);
@@ -2960,35 +3032,63 @@ find_lock_node_by_name(const TEXT * name,const struct LockNode * skip)
struct LockNode * ln;
#ifndef USE_SPLAY_TREE
for(ln = (struct LockNode *)LockList.mlh_Head ;
ln->ln_MinNode.mln_Succ != NULL ;
ln = (struct LockNode *)ln->ln_MinNode.mln_Succ)
{
if(ln != skip && compare_names(name,ln->ln_FullName) == SAME)
D(("searching for lock with name '%s'", name));
for(ln = (struct LockNode *)LockList.mlh_Head ;
ln->ln_MinNode.mln_Succ != NULL ;
ln = (struct LockNode *)ln->ln_MinNode.mln_Succ)
{
result = ln;
break;
if(ln != skip && compare_names(name,ln->ln_FullName) == SAME)
{
result = ln;
break;
}
}
if(result != NULL)
D(("found it (= 0x%08lx)", result));
else
D(("didn't find it"));
}
#else
{
struct splay_node * sn;
D(("looking up lock with name '%s'", name));
sn = splay_tree_find(&LockNameTree, (splay_key_t)name);
if(sn != NULL)
{
ln = (struct LockNode *)sn->sn_userdata;
ASSERT( ln != NULL );
if (ln != skip)
{
result = ln;
D(("found it (= 0x%08lx)", result));
}
else if (sn->sn_next != NULL)
{
result = (struct LockNode *)sn->sn_next->sn_userdata;
D(("found it, but can't use it, so using the next best entry (= 0x%08lx)", result));
if(result == NULL)
D(("...but didn't actually find it"));
}
else
{
D(("didn't find it"));
}
}
else
{
D(("didn't find it"));
}
}
#else
struct splay_node * sn;
sn = splay_tree_find(&LockNameTree, (splay_key_t)name);
if(sn != NULL)
{
ln = (struct LockNode *)sn->sn_userdata;
ASSERT( ln != NULL );
if (ln != skip)
result = ln;
else if (sn->sn_next != NULL)
result = (struct LockNode *)sn->sn_next->sn_userdata;
}
#endif /* USE_SPLAY_TREE */
return(result);
@@ -3659,6 +3759,8 @@ setup(
BOOL opt_prefer_core_protocol,
BOOL opt_session_setup_delay_unicode,
BOOL opt_write_behind,
int opt_smb_request_write_threshold,
int opt_smb_request_read_threshold,
const TEXT * device_name,
const TEXT * volume_name,
BOOL opt_add_volume,
@@ -3681,19 +3783,19 @@ setup(
NewList((struct List *)&LockList);
#ifdef USE_SPLAY_TREE
{
/* File names may not be unique. */
splay_tree_init(&FileNameTree, (splay_key_compare_t)compare_names);
FileNameTree.st_allow_duplicates = TRUE;
/* File names may not be unique. */
splay_tree_init(&FileNameTree, (splay_key_compare_t)compare_names);
FileNameTree.st_allow_duplicates = TRUE;
splay_tree_init(&FileAddressTree, compare_file_or_lock_by_address);
splay_tree_init(&FileAddressTree, compare_file_or_lock_by_address);
/* Lock names may not be unique. */
splay_tree_init(&LockNameTree, (splay_key_compare_t)compare_names);
LockNameTree.st_allow_duplicates = TRUE;
splay_tree_init(&LockAddressTree, compare_file_or_lock_by_address);
/* Lock names may not be unique. */
splay_tree_init(&LockNameTree, (splay_key_compare_t)compare_names);
LockNameTree.st_allow_duplicates = TRUE;
splay_tree_init(&LockAddressTree, compare_file_or_lock_by_address);
}
#endif /* USE_SPLAY_TREE */
MemoryPool = CreatePool(MEMF_ANY|MEMF_PUBLIC, 4096, 4096);
@@ -3898,6 +4000,8 @@ setup(
CaseSensitive,
opt_session_setup_delay_unicode,
opt_write_behind,
opt_smb_request_write_threshold,
opt_smb_request_read_threshold,
&error,
&smb_error_class,
&smb_error,
@@ -4082,15 +4186,15 @@ add_file_node(struct FileNode * fn)
AddTail((struct List *)&FileList,(struct Node *)fn);
#ifdef USE_SPLAY_TREE
{
fn->fn_SplayNameNode.sn_key = (splay_key_t)fn->fn_FullName;
fn->fn_SplayNameNode.sn_userdata = fn;
splay_tree_add(&FileNameTree, &fn->fn_SplayNameNode);
fn->fn_SplayNameNode.sn_key = (splay_key_t)fn->fn_FullName;
fn->fn_SplayNameNode.sn_userdata = fn;
splay_tree_add(&FileNameTree, &fn->fn_SplayNameNode);
fn->fn_SplayAddressNode.sn_key = (splay_key_t)fn;
fn->fn_SplayAddressNode.sn_userdata = fn;
splay_tree_add(&FileAddressTree, &fn->fn_SplayAddressNode);
fn->fn_SplayAddressNode.sn_key = (splay_key_t)fn;
fn->fn_SplayAddressNode.sn_userdata = fn;
splay_tree_add(&FileAddressTree, &fn->fn_SplayAddressNode);
}
#endif /* USE_SPLAY_TREE */
}
@@ -4104,10 +4208,17 @@ remove_file_node(struct FileNode * fn)
Remove((struct Node *)fn);
#ifdef USE_SPLAY_TREE
{
APTR found;
splay_tree_remove(&FileNameTree, &fn->fn_SplayNameNode, (splay_key_t)fn->fn_FullName);
splay_tree_remove(&FileAddressTree, NULL, (splay_key_t)fn);
found = splay_tree_remove(&FileNameTree, &fn->fn_SplayNameNode, (splay_key_t)fn->fn_FullName);
D(("file name node removal %s", found != NULL ? "succeeded" : "failed"));
found = splay_tree_remove(&FileAddressTree, NULL, (splay_key_t)fn);
D(("file address node removal %s", found != NULL ? "succeeded" : "failed"));
}
#endif /* USE_SPLAY_TREE */
}
@@ -4121,15 +4232,15 @@ add_lock_node(struct LockNode * ln)
AddTail((struct List *)&LockList,(struct Node *)ln);
#ifdef USE_SPLAY_TREE
{
ln->ln_SplayNameNode.sn_key = (splay_key_t)ln->ln_FullName;
ln->ln_SplayNameNode.sn_userdata = ln;
splay_tree_add(&LockNameTree, &ln->ln_SplayNameNode);
ln->ln_SplayNameNode.sn_key = (splay_key_t)ln->ln_FullName;
ln->ln_SplayNameNode.sn_userdata = ln;
splay_tree_add(&LockNameTree, &ln->ln_SplayNameNode);
ln->ln_SplayAddressNode.sn_key = (splay_key_t)ln;
ln->ln_SplayAddressNode.sn_userdata = ln;
splay_tree_add(&LockAddressTree, &ln->ln_SplayAddressNode);
ln->ln_SplayAddressNode.sn_key = (splay_key_t)ln;
ln->ln_SplayAddressNode.sn_userdata = ln;
splay_tree_add(&LockAddressTree, &ln->ln_SplayAddressNode);
}
#endif /* USE_SPLAY_TREE */
}
@@ -4143,10 +4254,17 @@ remove_lock_node(struct LockNode * ln)
Remove((struct Node *)ln);
#ifdef USE_SPLAY_TREE
{
APTR found;
splay_tree_remove(&LockNameTree, &ln->ln_SplayNameNode, ln->ln_SplayNameNode.sn_key);
splay_tree_remove(&LockAddressTree, NULL, (splay_key_t)ln);
found = splay_tree_remove(&LockNameTree, &ln->ln_SplayNameNode, ln->ln_SplayNameNode.sn_key);
D(("lock name node removal %s", found != NULL ? "succeeded" : "failed"));
found = splay_tree_remove(&LockAddressTree, NULL, (splay_key_t)ln);
D(("lock address node removal %s", found != NULL ? "succeeded" : "failed"));
}
#endif /* USE_SPLAY_TREE */
/* This will make the lock_is_invalid() tests return
@@ -5151,41 +5269,18 @@ restart_directory_scanning(const struct MsgPort * user,const TEXT * parent_dir_n
SHOWSTRING(parent_dir_name);
#ifndef USE_SPLAY_TREE
for(ln = (struct LockNode *)LockList.mlh_Head ;
ln->ln_MinNode.mln_Succ != NULL ;
ln = (struct LockNode *)ln->ln_MinNode.mln_Succ)
{
/* Try not to self-disrupt directory scanning while
* deleting the contents of the directory.
*/
if(ln->ln_LastUser == user)
continue;
if(compare_names(parent_dir_name,ln->ln_FullName) == SAME)
for(ln = (struct LockNode *)LockList.mlh_Head ;
ln->ln_MinNode.mln_Succ != NULL ;
ln = (struct LockNode *)ln->ln_MinNode.mln_Succ)
{
D(("restart scanning for '%s'", escape_name(ln->ln_FullName)));
/* Try not to self-disrupt directory scanning while
* deleting the contents of the directory.
*/
if(ln->ln_LastUser == user)
continue;
ln->ln_RestartExamine = TRUE;
}
}
#else
/* Find all the locks which share the same directory name. */
sn = splay_tree_find(&LockNameTree, (splay_key_t)parent_dir_name);
if(sn != NULL)
{
/* Check each lock in turn, restarting the directory
* scanning process unless the same program which
* requires the restart is the one currently
* doing the scanning.
*/
for((void)NULL ; sn != NULL ; sn = sn->sn_next)
{
ln = sn->sn_userdata;
if(ln->ln_LastUser != user)
if(compare_names(parent_dir_name,ln->ln_FullName) == SAME)
{
D(("restart scanning for '%s'", escape_name(ln->ln_FullName)));
@@ -5193,7 +5288,30 @@ restart_directory_scanning(const struct MsgPort * user,const TEXT * parent_dir_n
}
}
}
#else
{
/* Find all the locks which share the same directory name. */
sn = splay_tree_find(&LockNameTree, (splay_key_t)parent_dir_name);
if(sn != NULL)
{
/* Check each lock in turn, restarting the directory
* scanning process unless the same program which
* requires the restart is the one currently
* doing the scanning.
*/
for((void)NULL ; sn != NULL ; sn = sn->sn_next)
{
ln = sn->sn_userdata;
if(ln->ln_LastUser != user)
{
D(("restart scanning for '%s'", escape_name(ln->ln_FullName)));
ln->ln_RestartExamine = TRUE;
}
}
}
}
#endif /* USE_SPLAY_TREE */
LEAVE();
@@ -6087,24 +6205,34 @@ Action_FreeLock(
D(("lock on '%s'", escape_name(key->ln_FullName)));
#ifndef USE_SPLAY_TREE
for(ln = (struct LockNode *)LockList.mlh_Head ;
ln->ln_MinNode.mln_Succ != NULL ;
ln = (struct LockNode *)ln->ln_MinNode.mln_Succ)
{
if(ln == key)
for(ln = (struct LockNode *)LockList.mlh_Head ;
ln->ln_MinNode.mln_Succ != NULL ;
ln = (struct LockNode *)ln->ln_MinNode.mln_Succ)
{
found = ln;
break;
if(ln == key)
{
found = ln;
break;
}
}
}
#else
{
D(("looking up the lock address (what happened to trust?)"));
sn = splay_tree_find(&LockAddressTree, (splay_key_t)key);
if(sn != NULL)
found = (struct LockNode *)sn->sn_userdata;
sn = splay_tree_find(&LockAddressTree, (splay_key_t)key);
if(sn != NULL)
{
D(("found it"));
found = (struct LockNode *)sn->sn_userdata;
}
else
{
D(("didn't find it (this should never happen)"));
}
}
#endif /* USE_SPLAY_TREE */
/* This should never happen. */
@@ -8340,24 +8468,34 @@ Action_End(
found = NULL;
#ifndef USE_SPLAY_TREE
for(fn = (struct FileNode *)FileList.mlh_Head ;
fn->fn_MinNode.mln_Succ != NULL ;
fn = (struct FileNode *)fn->fn_MinNode.mln_Succ)
{
if(fn == which_fn)
for(fn = (struct FileNode *)FileList.mlh_Head ;
fn->fn_MinNode.mln_Succ != NULL ;
fn = (struct FileNode *)fn->fn_MinNode.mln_Succ)
{
found = fn;
break;
if(fn == which_fn)
{
found = fn;
break;
}
}
}
#else
{
D(("looking up the file address (what happened to trust?)"));
sn = splay_tree_find(&FileAddressTree, (splay_key_t)which_fn);
if(sn != NULL)
found = (struct FileNode *)sn->sn_userdata;
sn = splay_tree_find(&FileAddressTree, (splay_key_t)which_fn);
if(sn != NULL)
{
D(("found it"));
found = (struct FileNode *)sn->sn_userdata;
}
else
{
D(("didn't find it (this should never happen)"));
}
}
#endif /* USE_SPLAY_TREE */
if(found == NULL)
+104 -26
View File
@@ -483,16 +483,18 @@ smb_encode_smb_length (byte * p, int len)
/* 0x00 = NetBIOS session message */
p[0] = 0;
/* 0 = reserved */
p[1] = 0;
/* Length is a 17 bit integer, the most significant
* bit of which goes into bit #0. The other 7 bits
* are reserved.
*/
p[1] = (len >> 16) & 1;
/* Payload length in network byte order. */
/* Payload length in network byte order
* (least significant 16 bits).
*/
p[2] = (len & 0xFF00) >> 8;
p[3] = (len & 0xFF);
/* Length is actually a 17 bit integer. */
p[1] |= (len >> 16) & 1;
return &p[4];
}
@@ -1593,7 +1595,13 @@ smb_proc_close (struct smb_server *server, word fileid, dword wtime, int * error
* the file-id to be valid again after a reconnection.
*/
int
smb_proc_read (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, char *data, int * error_ptr)
smb_proc_read (
struct smb_server *server,
struct smb_dirent *finfo,
off_t offset,
long count,
char *data,
int * error_ptr)
{
char *buf = server->transmit_buffer;
int result;
@@ -1643,7 +1651,13 @@ smb_proc_read (struct smb_server *server, struct smb_dirent *finfo, off_t offset
* call.
*/
int
smb_proc_read_raw (struct smb_server *server, struct smb_dirent *finfo, const QUAD * const offset_quad, long count, char *data, int * error_ptr)
smb_proc_read_raw (
struct smb_server *server,
struct smb_dirent *finfo,
const QUAD * const offset_quad,
long count,
char *data,
int * error_ptr)
{
char *buf = server->transmit_buffer;
int result;
@@ -1678,7 +1692,13 @@ smb_proc_read_raw (struct smb_server *server, struct smb_dirent *finfo, const QU
}
int
smb_proc_write (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, const char *data, int * error_ptr)
smb_proc_write (
struct smb_server *server,
struct smb_dirent *finfo,
off_t offset,
long count,
const char *data,
int * error_ptr)
{
int result;
char *buf = server->transmit_buffer;
@@ -1717,7 +1737,13 @@ smb_proc_write (struct smb_server *server, struct smb_dirent *finfo, off_t offse
}
int
smb_proc_write_raw (struct smb_server *server, struct smb_dirent *finfo, const QUAD * const offset_quad, long count, const char *data, int * error_ptr)
smb_proc_write_raw (
struct smb_server *server,
struct smb_dirent *finfo,
const QUAD * const offset_quad,
long count,
const char *data,
int * error_ptr)
{
char *buf = server->transmit_buffer;
int num_bytes_written = 0;
@@ -1893,7 +1919,13 @@ smb_proc_write_raw (struct smb_server *server, struct smb_dirent *finfo, const Q
}
int
smb_proc_writex (struct smb_server *server, struct smb_dirent *finfo, const QUAD * const offset_quad, long count, const char *data, int * error_ptr)
smb_proc_writex (
struct smb_server *server,
struct smb_dirent *finfo,
const QUAD * const offset_quad,
long count,
const char *data,
int * error_ptr)
{
char *buf = server->transmit_buffer;
int result;
@@ -1961,7 +1993,13 @@ smb_proc_writex (struct smb_server *server, struct smb_dirent *finfo, const QUAD
}
int
smb_proc_readx (struct smb_server *server, struct smb_dirent *finfo, const QUAD * const offset_quad, long count, char *data, int * error_ptr)
smb_proc_readx (
struct smb_server *server,
struct smb_dirent *finfo,
const QUAD * const offset_quad,
long count,
char *data,
int * error_ptr)
{
char *buf = server->transmit_buffer;
int result;
@@ -2021,7 +2059,14 @@ smb_proc_readx (struct smb_server *server, struct smb_dirent *finfo, const QUAD
/* smb_proc_lockingX: We don't chain any further packets to the initial one */
int
smb_proc_lockingX (struct smb_server *server, struct smb_dirent *finfo, const struct smb_lkrng *locks, int num_entries, int mode, long timeout, int * error_ptr)
smb_proc_lockingX (
struct smb_server *server,
struct smb_dirent *finfo,
const struct smb_lkrng *locks,
int num_entries,
int mode,
long timeout,
int * error_ptr)
{
int result;
int num_locks, num_unlocks;
@@ -2073,7 +2118,7 @@ smb_proc_lockingX (struct smb_server *server, struct smb_dirent *finfo, const st
return result;
}
/* smb_proc_do_create: We expect entry->attry & entry->ctime to be set. */
/* smb_proc_do_create: We expect entry->attry and entry->ctime to be set. */
int
smb_proc_create (struct smb_server *server, const char *path, int len, struct smb_dirent *entry, int * error_ptr)
{
@@ -2153,7 +2198,13 @@ smb_proc_create (struct smb_server *server, const char *path, int len, struct sm
}
int
smb_proc_mv (struct smb_server *server, const char *old_path, const int old_path_len, const char *new_path, const int new_path_len, int * error_ptr)
smb_proc_mv (
struct smb_server *server,
const char *old_path,
const int old_path_len,
const char *new_path,
const int new_path_len,
int * error_ptr)
{
char *p;
char *buf = server->transmit_buffer;
@@ -2373,12 +2424,10 @@ smb_decode_dirent (const char *p, struct smb_dirent *entry)
entry->size_low = DVAL (p, 5);
entry->size_high = 0;
/* The name is given in 8.3 MS-DOS style format,
* including the "." delimiter. This is a NUL-
* terminated OEM string, with one byte per
* character. If the name is shorter than 12
* characters, it is padded with " " (space)
* characters.
/* The name is given in 8.3 MS-DOS style format, including the "."
* delimiter. This is a NUL-terminated OEM string, with one byte per
* character. If the name is shorter than 12 characters, it is
* padded with " " (space) characters.
*/
name_len = 12;
@@ -2423,7 +2472,13 @@ smb_decode_dirent (const char *p, struct smb_dirent *entry)
* Note that it is for short directory name seeks, i.e.: protocol < PROTOCOL_LANMAN2
*/
static int
smb_proc_readdir_short (struct smb_server *server, const char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr)
smb_proc_readdir_short (
struct smb_server *server,
const char *path,
int fpos,
int cache_size,
struct smb_dirent *entry,
int * error_ptr)
{
char *p;
char *buf;
@@ -2712,7 +2767,12 @@ smb_get_dirent_name(char *p,int level,char ** name_ptr,int * len_ptr)
/* interpret a long filename structure */
static int
smb_decode_long_dirent (const struct smb_server *server, const char *p, struct smb_dirent *finfo, int level, int * entry_length_ptr)
smb_decode_long_dirent (
const struct smb_server *server,
const char *p,
struct smb_dirent *finfo,
int level,
int * entry_length_ptr)
{
int success = TRUE;
@@ -2948,7 +3008,13 @@ smb_decode_long_dirent (const struct smb_server *server, const char *p, struct s
}
static int
smb_proc_readdir_long (struct smb_server *server, const char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr)
smb_proc_readdir_long (
struct smb_server *server,
const char *path,
int fpos,
int cache_size,
struct smb_dirent *entry,
int * error_ptr)
{
int max_matches = 512; /* this should actually be based on the max_recv value */
@@ -3317,7 +3383,13 @@ smb_proc_readdir_long (struct smb_server *server, const char *path, int fpos, in
}
int
smb_proc_readdir (struct smb_server *server, const char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr)
smb_proc_readdir (
struct smb_server *server,
const char *path,
int fpos,
int cache_size,
struct smb_dirent *entry,
int * error_ptr)
{
int result;
@@ -3410,7 +3482,13 @@ smb_proc_getattr_core (struct smb_server *server, const char *path, int len, str
}
int
smb_query_path_information(struct smb_server *server, const char *path, int len, int fid, struct smb_dirent *entry, int * error_ptr)
smb_query_path_information(
struct smb_server *server,
const char *path,
int len,
int fid,
struct smb_dirent *entry,
int * error_ptr)
{
unsigned char *outbuf = server->transmit_buffer;
dword ext_file_attributes;
+82 -33
View File
@@ -95,6 +95,8 @@ smba_connect (
int opt_case_sensitive,
int opt_session_setup_delay_unicode,
int opt_write_behind,
int opt_smb_request_write_threshold,
int opt_smb_request_read_threshold,
int * error_ptr,
int * smb_error_class_ptr,
int * smb_error_ptr,
@@ -152,6 +154,22 @@ smba_connect (
LOG(("delay use of unicode during session setup = %s\n",opt_session_setup_delay_unicode ? "yes" : "no"));
/* Do not send SMB header and payload for write operations separately,
* but in a single chunk if their combined size is smaller than
* or equal to this threshold value.
*/
res->server.smb_write_threshold = opt_smb_request_write_threshold;
LOG(("SMB write request threshold size = %ld bytes\n", res->server.smb_write_threshold));
/* Do not receive SMB header and payload for read operations separately,
* but in a single chunk if their combined size is smaller than
* or equal to this threshold value.
*/
res->server.smb_read_threshold = opt_smb_request_read_threshold;
LOG(("SMB read request threshold size = %ld bytes\n", res->server.smb_read_threshold));
/* Enable asynchronous SMB_COM_WRITE_RAW operations? */
res->server.write_behind = opt_write_behind;
@@ -198,6 +216,8 @@ smba_connect (
if(servent != NULL)
{
data.addr.sin_port = servent->s_port;
LOG(("using port number %ld\n",ntohs(data.addr.sin_port)));
}
else
{
@@ -214,6 +234,8 @@ smba_connect (
if(0 < n && n < 65536)
{
data.addr.sin_port = htons (n);
LOG(("using port number %ld\n",n));
}
else
{
@@ -234,19 +256,31 @@ smba_connect (
}
else if (res->server.raw_smb)
{
int port;
servent = getservbyname("microsoft-ds","tcp");
if(servent != NULL)
data.addr.sin_port = servent->s_port;
port = servent->s_port;
else
data.addr.sin_port = htons (445);
port = htons (445);
LOG(("using port number %ld\n",ntohs(port)));
data.addr.sin_port = port;
}
else
{
int port;
servent = getservbyname("netbios-ssn","tcp");
if(servent != NULL)
data.addr.sin_port = servent->s_port;
port = servent->s_port;
else
data.addr.sin_port = htons (139);
port = htons (139);
LOG(("using port number %ld\n",ntohs(port)));
data.addr.sin_port = port;
}
data.fd = socket (AF_INET, SOCK_STREAM, 0);
@@ -592,7 +626,7 @@ write_attr (smba_file_t * f, int * error_ptr)
f->dirent.mtime = mtime;
f->dirent.attr = attr;
/* If the attributes need to be updated, we cannot used smb_proc_setattrE(),
/* If the attributes need to be updated, we cannot use smb_proc_setattrE(),
* because that only updates the "time of last write access", but not the
* attributes.
*/
@@ -1376,7 +1410,8 @@ smba_readdir (smba_file_t * f, int offs, void *callback_data, smba_callback_t ca
f->dircache->len = 0;
f->dircache->base = cache_index;
num_entries = smb_proc_readdir (&f->server->server, f->dirent.complete_path, cache_index, f->dircache->cache_size, f->dircache->cache, error_ptr);
num_entries = smb_proc_readdir (&f->server->server, f->dirent.complete_path, cache_index, f->dircache->cache_size,
f->dircache->cache, error_ptr);
/* We stop on error, or if the directory is empty. */
if (num_entries <= 0)
@@ -1475,12 +1510,12 @@ allocate_path_name(const smba_file_t * dir, const char *name, size_t * path_name
if(path != NULL)
{
memcpy (path, dir->dirent.complete_path, dir_len);
path[dir_len] = DOS_PATHSEP;
path[dir_len++] = DOS_PATHSEP;
memcpy(&path[dir_len], name, len+1); /* length includes terminating NUL character */
ASSERT( path_name_len_ptr != NULL );
(*path_name_len_ptr) = dir_len + 1 + len;
(*path_name_len_ptr) = dir_len + len;
}
return(path);
@@ -1846,10 +1881,28 @@ extract_service (
char * share_start;
char * root_start;
char * complete_service;
char * service_copy;
char * service_copy = NULL;
char * service_name;
int result = -1;
if (strlen (service) < 4)
{
report_error("Service name '%s' is too short.",service);
(*error_ptr) = EINVAL;
goto out;
}
if (service[0] != '/')
{
report_error("Service name '%s' must begin with '/'.",service);
(*error_ptr) = EINVAL;
goto out;
}
service_copy = malloc(strlen(service)+1);
if(service_copy == NULL)
{
@@ -1861,28 +1914,11 @@ extract_service (
}
strcpy (service_copy, service);
complete_service = service_copy;
if (strlen (complete_service) < 4)
{
report_error("Service name '%s' is too short.",complete_service);
(*error_ptr) = EINVAL;
goto out;
}
if (complete_service[0] != '/')
{
report_error("Service name '%s' must begin with '/'.",complete_service);
(*error_ptr) = EINVAL;
goto out;
}
while (complete_service[0] == '/')
complete_service += 1;
complete_service++;
share_start = strchr (complete_service, '/');
if (share_start == NULL)
@@ -1920,20 +1956,29 @@ extract_service (
len--;
service_name[len] = '\0';
if(len > tcp_service_name_size)
{
report_error("TCP service name/port number is too long in '%s' (%ld characters are possible).",service_name,tcp_service_name_size);
(*error_ptr) = EINVAL;
goto out;
}
}
if (strlen (complete_service) > 63)
if (strlen (complete_service) > server_size)
{
report_error("Server name is too long in '%s' (%ld characters are possible).",service,63);
report_error("Server name is too long in '%s' (%ld characters are possible).",service,server_size);
(*error_ptr) = ENAMETOOLONG;
goto out;
}
if (strlen (share_start) > 255)
if (strlen (share_start) > share_size)
{
report_error("Share name is too long in '%s' (%ld characters are possible).",service,255);
report_error("Share name is too long in '%s' (%ld characters are possible).",service,share_size);
(*error_ptr) = ENAMETOOLONG;
@@ -1971,6 +2016,8 @@ smba_start(
int opt_case_sensitive,
int opt_session_setup_delay_unicode,
int opt_write_behind,
int opt_smb_request_write_threshold,
int opt_smb_request_read_threshold,
int * error_ptr,
int * smb_error_class_ptr,
int * smb_error_ptr,
@@ -2133,7 +2180,7 @@ smba_start(
/* Make sure the hostname is 16 characters or less (for NetBIOS) */
if (!opt_raw_smb && strlen (host_name) > 16)
{
report_error("Server name '%s' is too long (max %ld characters).", host_name, 16);
report_error("Server name '%s' is too long (%ld characters are possible).", host_name, 16);
(*error_ptr) = ENAMETOOLONG;
goto out;
@@ -2222,6 +2269,8 @@ smba_start(
opt_case_sensitive,
opt_session_setup_delay_unicode,
opt_write_behind,
opt_smb_request_write_threshold,
opt_smb_request_read_threshold,
error_ptr,
smb_error_class_ptr,
smb_error_ptr,
+1 -1
View File
@@ -162,7 +162,7 @@ int smba_rmdir(smba_server_t *s, const char *path, int *error_ptr);
int smba_rename(smba_server_t *s, const char *from, const char *to, int *error_ptr);
int smba_statfs(smba_server_t *s, long *bsize, long *blocks, long *bfree, int *error_ptr);
void smb_invalidate_all_inodes(struct smb_server *server);
int smba_start(const char *service, const char *opt_workgroup, const char *opt_username, const char *opt_password, const char *opt_clientname, const char *opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, int opt_raw_smb, int opt_unicode, int opt_prefer_core_protocol, int opt_case_sensitive, int opt_session_setup_delay_unicode, int opt_write_behind, int *error_ptr, int *smb_error_class_ptr, int *smb_error_ptr, smba_connect_parameters_t *smba_connect_par, smba_server_t **smba_server_ptr);
int smba_start(const char *service, const char *opt_workgroup, const char *opt_username, const char *opt_password, const char *opt_clientname, const char *opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, int opt_raw_smb, int opt_unicode, int opt_prefer_core_protocol, int opt_case_sensitive, int opt_session_setup_delay_unicode, int opt_write_behind, int opt_smb_request_write_threshold, int opt_smb_request_read_threshold, int *error_ptr, int *smb_error_class_ptr, int *smb_error_ptr, smba_connect_parameters_t *smba_connect_par, smba_server_t **smba_server_ptr);
int smba_get_dircache_size(struct smba_server *server);
int smba_change_dircache_size(struct smba_server *server, int cache_size);
+5 -5
View File
@@ -1,6 +1,6 @@
#define VERSION 2
#define REVISION 5
#define DATE "16.12.2018"
#define VERS "smbfs 2.5"
#define VSTRING "smbfs 2.5 (16.12.2018)\r\n"
#define VERSTAG "\0$VER: smbfs 2.5 (16.12.2018)"
#define REVISION 8
#define DATE "19.12.2018"
#define VERS "smbfs 2.8"
#define VSTRING "smbfs 2.8 (19.12.2018)\r\n"
#define VERSTAG "\0$VER: smbfs 2.8 (19.12.2018)"
+1 -1
View File
@@ -1 +1 @@
5
8
+411 -229
View File
@@ -203,6 +203,7 @@ smb_receive_raw (
int * error_ptr)
{
unsigned char netbios_session_buf[256];
unsigned char * netbios_session_data;
int netbios_session_payload_size;
int len, result;
@@ -211,10 +212,27 @@ smb_receive_raw (
server->rcls = 0;
server->err = 0;
/* If the NetBIOS header needs to be returned, receive it along
* with the SMB message and whatever follows.
*/
if (want_header)
{
LOG(("NetBIOS header will be returned as part of the buffer\n"));
netbios_session_data = target;
}
/* Otherwise store the NetBIOS header in a separate buffer. */
else
{
LOG(("NetBIOS header will be processed separately\n"));
netbios_session_data = netbios_session_buf;
}
re_recv:
/* Read the NetBIOS session header (rfc-1002, section 4.3.1) */
result = receive_all (sock_fd, netbios_session_buf, NETBIOS_HEADER_SIZE, error_ptr);
result = receive_all (sock_fd, netbios_session_data, NETBIOS_HEADER_SIZE, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
@@ -231,12 +249,12 @@ smb_receive_raw (
goto out;
}
netbios_session_payload_size = (int)smb_len(netbios_session_buf);
netbios_session_payload_size = (int)smb_len(netbios_session_data);
SHOWVALUE(netbios_session_payload_size);
#if defined(DUMP_SMB)
{
if(command != 0 && netbios_session_buf[0] != 0x00 && netbios_session_payload_size > 0)
if(command != 0 && netbios_session_data[0] != 0x00 && netbios_session_payload_size > 0)
{
/* We only want to show what's in the first few
* bytes of a session packet. Since we only support
@@ -248,7 +266,7 @@ smb_receive_raw (
if(netbios_session_payload_size > 256 - NETBIOS_HEADER_SIZE)
netbios_session_payload_size = 256 - NETBIOS_HEADER_SIZE;
result = receive_all (sock_fd, &netbios_session_buf[NETBIOS_HEADER_SIZE], netbios_session_payload_size - NETBIOS_HEADER_SIZE, error_ptr);
result = receive_all (sock_fd, &netbios_session_data[NETBIOS_HEADER_SIZE], netbios_session_payload_size - NETBIOS_HEADER_SIZE, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
@@ -265,17 +283,17 @@ smb_receive_raw (
goto out;
}
dump_netbios_header(__FILE__,__LINE__,netbios_session_buf,&netbios_session_buf[NETBIOS_HEADER_SIZE],netbios_session_payload_size);
dump_netbios_header(__FILE__,__LINE__,netbios_session_data,&netbios_session_data[NETBIOS_HEADER_SIZE],netbios_session_payload_size);
}
else
{
dump_netbios_header(__FILE__,__LINE__,netbios_session_buf,NULL,0);
dump_netbios_header(__FILE__,__LINE__,netbios_session_data,NULL,0);
}
}
#endif /* defined(DUMP_SMB) */
/* Check the session type. */
switch (netbios_session_buf[0])
switch (netbios_session_data[0])
{
/* 0x00 == session message */
case 0x00:
@@ -300,7 +318,7 @@ smb_receive_raw (
*/
if(command != 0)
{
LOG (("Invalid session header type 0x%02lx\n", netbios_session_buf[0]));
LOG (("Invalid session header type 0x%02lx\n", netbios_session_data[0]));
(*error_ptr) = error_invalid_netbios_session;
@@ -323,12 +341,11 @@ smb_receive_raw (
goto out;
}
/* Prepend the NetBIOS header to what is read? */
/* Did we read the NetBIOS header already? Make sure that
* the data to follow goes into the right receive buffer.
*/
if (want_header)
{
memcpy (target, netbios_session_buf, NETBIOS_HEADER_SIZE);
target += NETBIOS_HEADER_SIZE;
}
/* This is an optimization for the SMB_COM_READ and SMB_COM_READ_ANDX
* commands, which tries to avoid copying the received data twice. To
@@ -337,129 +354,248 @@ smb_receive_raw (
* begins. Then we read the data, storing it directly in the
* receive buffer rather than in the packet buffer, from which
* it would otherwise have to be retrieved later.
*
* Note that this optimization may still not take effect because the
* amount of data expected to be received can be so small that it
* may make little sense to break up reception into two separate
* recv() calls.
*/
if(input_payload != NULL)
{
int num_bytes_received = 0;
LOG(("input_payload=0x%08lx, payload_size=%ld\n", input_payload, input_payload_size));
if(command == SMBreadX)
/* Receive SMB message header and payload separately? */
if(len > server->smb_read_threshold)
{
int data_length;
int data_offset;
int num_bytes_received = 0;
/* We need to read the following data:
*
* 0: 32 bytes of SMB message header
* 32: 1 byte of word count
* 33: 1 byte of andxcommand
* 34: 1 byte of andxreserved
* 35: 2 bytes of andxoffset
* 37: 2 bytes of available
* 39: 2 bytes of datacompactionmode
* 41: 2 bytes of reserved
* 43: 2 bytes of datalength
* 45: 2 bytes of dataoffset
* 47: 10 bytes of reserved
* 57: 2 bytes of bytecount
*
* This adds up to 59 bytes.
*/
LOG(("receiving SMB message and payload separately\n"));
LOG(("SMBreadX: reading the first %ld bytes\n", 59));
LOG(("input_payload=0x%08lx, payload_size=%ld\n", input_payload, input_payload_size));
result = receive_all (sock_fd, target, 59, error_ptr);
if (result < 0)
if(command == SMBreadX)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
int data_length;
int data_offset;
num_bytes_received += result;
/* We need to read the following data:
*
* 0: 32 bytes of SMB message header
* 32: 1 byte of word count
* 33: 1 byte of andxcommand
* 34: 1 byte of andxreserved
* 35: 2 bytes of andxoffset
* 37: 2 bytes of available
* 39: 2 bytes of datacompactionmode
* 41: 2 bytes of reserved
* 43: 2 bytes of datalength
* 45: 2 bytes of dataoffset
* 47: 10 bytes of reserved
* 57: 2 bytes of bytecount
*
* This adds up to 59 bytes.
*/
ASSERT( num_bytes_received == 59 );
LOG(("SMBreadX: reading the first %ld bytes\n", 59));
/* End of file reached? */
if(num_bytes_received < 59)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
data_offset = WVAL(target, 45);
SHOWVALUE(data_offset);
/* Skip the padding bytes, if any. */
if(data_offset > 59)
{
result = receive_all (sock_fd, target + 59, data_offset - 59, error_ptr);
result = receive_all (sock_fd, target, 59, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
num_bytes_received += result;
ASSERT( num_bytes_received == 59 );
/* End of file reached? */
if(result < data_offset - 59)
if(num_bytes_received < 59)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
data_offset = WVAL(target, 45);
SHOWVALUE(data_offset);
/* Skip the padding bytes, if any. */
if(data_offset > 59)
{
LOG (("skipping %ld padding bytes\n", data_offset - 59));
result = receive_all (sock_fd, target + 59, data_offset - 59, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
/* End of file reached? */
if(result < data_offset - 59)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
num_bytes_received += result;
}
data_length = WVAL(target, 43);
SHOWVALUE(data_length);
ASSERT( data_length <= input_payload_size );
result = receive_all (sock_fd, input_payload, data_length, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < data_length)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
num_bytes_received += result;
/* This should never happen, but then we better make sure to
* read the entire message.
*/
if(num_bytes_received < len)
{
LOG(("reading the remaining %ld bytes; this should never happen\n", len - num_bytes_received ));
result = receive_all (sock_fd, &target[num_bytes_received], len - num_bytes_received, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < len - num_bytes_received)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
}
}
data_length = WVAL(target, 43);
SHOWVALUE(data_length);
result = receive_all (sock_fd, input_payload, data_length, error_ptr);
if (result < 0)
else
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
int count_of_bytes_returned;
int count_of_bytes_to_read;
int buffer_format;
if(result < data_length)
{
/* End of file */
LOG (("EOF\n"));
ASSERT( command == SMBread );
(*error_ptr) = error_end_of_file;
/* We need to read the following data:
*
* 0: 32 bytes of SMB message header
* 32: 1 byte of word count
* 33: 2 bytes of 'count of bytes returned' (1 word)
* 35: 8 bytes of reserved data (4 words)
* 43: 2 bytes of 'byte count' (1 word)
* 45: 1 byte of 'buffer format'
* 46: 2 bytes of 'count of bytes to read' (1 word).
*
* This adds up to 48 bytes.
*/
result = -1;
goto out;
}
LOG(("SMBread: reading the first %ld bytes\n", 48));
num_bytes_received += result;
/* This should never happen, but then we better make sure to
* read the entire message.
*/
if(num_bytes_received < len)
{
LOG(("reading the remaining %ld bytes; this should never happen\n", len - num_bytes_received ));
result = receive_all (sock_fd, &target[num_bytes_received], len - num_bytes_received, error_ptr);
result = receive_all (sock_fd, target, 48, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < len - num_bytes_received)
num_bytes_received += result;
ASSERT( num_bytes_received == 48 );
/* End of file reached? */
if(num_bytes_received < 48)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
/* So we read the header. Now we need to figure out if the
* data is in the expected format, and how many bytes are
* waiting to be read.
*/
/* The buffer format must be 1. */
buffer_format = BVAL(target, 45);
LOG(("buffer format = %ld, should be %ld\n", buffer_format, 1));
if(buffer_format != 1)
{
LOG(("buffer format %ld not supported\n", buffer_format));
(*error_ptr) = error_invalid_buffer_format;
result = -1;
goto out;
}
count_of_bytes_returned = WVAL(target, 33);
count_of_bytes_to_read = WVAL(target, 46);
/* That should never be more data than the read buffer may hold. */
ASSERT( count_of_bytes_to_read <= input_payload_size );
ASSERT( count_of_bytes_to_read <= count_of_bytes_returned );
ASSERT( count_of_bytes_returned <= input_payload_size );
LOG(("count of bytes to read = %ld, should be <= %ld\n", count_of_bytes_to_read, input_payload_size));
if(count_of_bytes_returned > input_payload_size)
{
LOG(("this is too much data\n"));
(*error_ptr) = error_message_exceeds_buffer_size;
result = -1;
goto out;
}
result = receive_all (sock_fd, input_payload, count_of_bytes_to_read, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < count_of_bytes_to_read)
{
/* End of file */
LOG (("EOF\n"));
@@ -469,100 +605,78 @@ smb_receive_raw (
result = -1;
goto out;
}
num_bytes_received += result;
ASSERT( count_of_bytes_to_read == count_of_bytes_returned );
if(count_of_bytes_to_read < count_of_bytes_returned)
{
LOG(("fewer data available than should be delivered; setting the remainder (%ld bytes) to 0.\n", count_of_bytes_returned - count_of_bytes_to_read));
memset(&input_payload[count_of_bytes_to_read],0,count_of_bytes_returned - count_of_bytes_to_read);
}
/* This should never happen, but then we better make sure to
* read the entire message.
*/
if(num_bytes_received < len)
{
LOG(("reading the remaining %ld bytes; this should never happen\n", len - num_bytes_received ));
result = receive_all (sock_fd, &target[num_bytes_received], len - num_bytes_received, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < len - num_bytes_received)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
}
#if defined(DUMP_SMB)
{
/* If want_header==0 then this is the data returned by SMB_COM_READ_RAW. */
dump_smb(__FILE__,__LINE__,!want_header,target,48,smb_packet_to_consumer,server->max_recv);
if(buffer_format == 1)
dump_smb(__FILE__,__LINE__,!want_header,input_payload,num_bytes_received - 48,smb_packet_to_consumer,server->max_recv);
if(num_bytes_received < len && result > 0)
dump_smb(__FILE__,__LINE__,!want_header,&target[num_bytes_received],result,smb_packet_to_consumer,server->max_recv);
}
#endif /* defined(DUMP_SMB) */
}
result = num_bytes_received;
}
/* No, read both as a single chunk through recv() and pick
* the SMB message header and its payload apart later. This
* is intended to improve small read operation performance
* for which two separate recv() operations may introduce
* additional delays in processing.
*/
else
{
int count_of_bytes_returned;
int count_of_bytes_to_read;
int buffer_format;
LOG(("receiving SMB message and payload in one chunk\n"));
ASSERT( command == SMBread );
/* We need to read the following data:
*
* 0: 32 bytes of SMB message header
* 32: 1 byte of word count
* 33: 2 bytes of 'count of bytes returned' (1 word)
* 35: 8 bytes of reserved data (4 words)
* 43: 2 bytes of 'byte count' (1 word)
* 45: 1 byte of 'buffer format'
* 46: 2 bytes of 'count of bytes to read' (1 word).
*
* This adds up to 48 bytes.
*/
LOG(("SMBread: reading the first %ld bytes\n", 48));
result = receive_all (sock_fd, target, 48, error_ptr);
result = receive_all (sock_fd, target, len, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
num_bytes_received += result;
ASSERT( num_bytes_received == 48 );
/* End of file reached? */
if(num_bytes_received < 48)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
/* So we read the header. Now we need to figure out if the
* data is in the expected format, and how many bytes are
* waiting to be read.
*/
/* The buffer format must be 1. */
buffer_format = BVAL(target, 45);
LOG(("buffer format = %ld, should be %ld\n", buffer_format, 1));
if(buffer_format != 1)
{
LOG(("buffer format %ld not supported\n", buffer_format));
(*error_ptr) = error_invalid_buffer_format;
result = -1;
goto out;
}
count_of_bytes_returned = WVAL(target, 33);
count_of_bytes_to_read = WVAL(target, 46);
/* That should never be more data than the read buffer may hold. */
ASSERT( count_of_bytes_to_read <= input_payload_size );
ASSERT( count_of_bytes_to_read <= count_of_bytes_returned );
ASSERT( count_of_bytes_returned <= input_payload_size );
LOG(("count of bytes to read = %ld, should be <= %ld\n", count_of_bytes_to_read, input_payload_size));
if(count_of_bytes_returned > input_payload_size)
{
(*error_ptr) = error_message_exceeds_buffer_size;
result = -1;
goto out;
}
result = receive_all (sock_fd, input_payload, count_of_bytes_to_read, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < count_of_bytes_to_read)
if(result < len)
{
/* End of file */
LOG (("EOF\n"));
@@ -573,58 +687,85 @@ smb_receive_raw (
goto out;
}
num_bytes_received += result;
ASSERT( count_of_bytes_to_read == count_of_bytes_returned );
if(count_of_bytes_to_read < count_of_bytes_returned)
{
LOG(("fewer data available than should be delivered; setting the remainder (%ld bytes) to 0.\n", count_of_bytes_returned - count_of_bytes_to_read));
memset(&input_payload[count_of_bytes_to_read],0,count_of_bytes_returned - count_of_bytes_to_read);
}
/* This should never happen, but then we better make sure to
* read the entire message.
*/
if(num_bytes_received < len)
{
LOG(("reading the remaining %ld bytes; this should never happen\n", len - num_bytes_received ));
result = receive_all (sock_fd, &target[num_bytes_received], len - num_bytes_received, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < len - num_bytes_received)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
}
#if defined(DUMP_SMB)
{
/* If want_header==0 then this is the data returned by SMB_COM_READ_RAW. */
dump_smb(__FILE__,__LINE__,!want_header,target,48,smb_packet_to_consumer,server->max_recv);
if(buffer_format == 1)
dump_smb(__FILE__,__LINE__,!want_header,input_payload,num_bytes_received - 48,smb_packet_to_consumer,server->max_recv);
if(num_bytes_received < len && result > 0)
dump_smb(__FILE__,__LINE__,!want_header,&target[num_bytes_received],result,smb_packet_to_consumer,server->max_recv);
dump_smb(__FILE__,__LINE__,!want_header,target,result,smb_packet_to_consumer,server->max_recv);
}
#endif /* defined(DUMP_SMB) */
}
result = num_bytes_received;
if(command == SMBreadX)
{
int data_length;
int data_offset;
data_offset = WVAL(target, 45);
SHOWVALUE(data_offset);
data_length = WVAL(target, 43);
SHOWVALUE(data_length);
ASSERT( data_offset < len );
ASSERT( data_offset + data_length <= len );
ASSERT( data_length <= input_payload_size );
memcpy(input_payload, &target[data_offset], data_length);
}
else
{
int count_of_bytes_returned;
int count_of_bytes_to_read;
int buffer_format;
ASSERT( command == SMBread );
/* The buffer format must be 1. */
buffer_format = BVAL(target, 45);
LOG(("buffer format = %ld, should be %ld\n", buffer_format, 1));
if(buffer_format != 1)
{
LOG(("buffer format %ld not supported\n", buffer_format));
(*error_ptr) = error_invalid_buffer_format;
result = -1;
goto out;
}
count_of_bytes_returned = WVAL(target, 33);
count_of_bytes_to_read = WVAL(target, 46);
/* That should never be more data than the read buffer may hold. */
ASSERT( count_of_bytes_to_read <= input_payload_size );
ASSERT( count_of_bytes_to_read <= count_of_bytes_returned );
ASSERT( count_of_bytes_returned <= input_payload_size );
LOG(("count of bytes to read = %ld, should be <= %ld\n", count_of_bytes_to_read, input_payload_size));
if(count_of_bytes_returned > input_payload_size)
{
LOG(("this is too much data\n"));
(*error_ptr) = error_message_exceeds_buffer_size;
result = -1;
goto out;
}
memcpy(input_payload, &target[48], count_of_bytes_to_read);
ASSERT( count_of_bytes_to_read == count_of_bytes_returned );
if(count_of_bytes_to_read < count_of_bytes_returned)
{
LOG(("fewer data available than should be delivered; setting the remainder (%ld bytes) to 0.\n", count_of_bytes_returned - count_of_bytes_to_read));
memset(&input_payload[count_of_bytes_to_read],0,count_of_bytes_returned - count_of_bytes_to_read);
}
}
}
}
else
{
@@ -660,7 +801,13 @@ smb_receive_raw (
}
static int
smb_receive (struct smb_server *server, int command, int sock_fd, void * input_payload, int payload_size, int * error_ptr)
smb_receive (
struct smb_server *server,
int command,
int sock_fd,
void * input_payload,
int payload_size,
int * error_ptr)
{
byte * packet = server->transmit_buffer;
int result;
@@ -953,7 +1100,7 @@ smb_connect (struct smb_server *server, int * error_ptr)
server->mount_data.fd = result;
}
LOG(("connecting to server %s with socket %ld\n", Inet_NtoA(server->mount_data.addr.sin_addr.s_addr), server->mount_data.fd));
LOG(("connecting to server %s:%ld with socket %ld\n", Inet_NtoA(server->mount_data.addr.sin_addr.s_addr), ntohs(server->mount_data.addr.sin_port), server->mount_data.fd));
/* Wait a certain time period for the connection attempt to succeed? */
if(server->timeout > 0)
@@ -1162,7 +1309,13 @@ smb_check_server_connection(struct smb_server *server, int error)
* case of error.
*/
int
smb_request (struct smb_server *server, int command, void * input_payload, const void * output_payload, int payload_size, int * error_ptr)
smb_request (
struct smb_server *server,
int command,
void * input_payload,
const void * output_payload,
int payload_size,
int * error_ptr)
{
unsigned char *buffer = server->transmit_buffer;
int sock_fd = server->mount_data.fd;
@@ -1203,7 +1356,29 @@ smb_request (struct smb_server *server, int command, void * input_payload, const
ASSERT( payload_size < smb_len(buffer) );
ASSERT( len > payload_size );
len -= payload_size;
/* Send SMB message header and payload separately? */
if(len > server->smb_write_threshold)
{
LOG(("sending SMB message and payload separately\n"));
len -= payload_size;
}
/* No, combine both into a single chunk which will be
* transmitted with a single send(). This is intended
* to improve small write operation performance for
* which two separate send() operations may not succeed
* in nudging the TCP/IP stack to transmit the data just
* yet (Nagle algorithm, etc.).
*/
else
{
LOG(("sending SMB message and payload in one chunk\n"));
memcpy(&buffer[len - payload_size], output_payload, payload_size);
output_payload = NULL;
payload_size = 0;
}
}
LOG (("len = %ld, cmd = 0x%lx, input_payload=0x%08lx, output_payload=0x%08lx, payload_size=%ld\n", len, buffer[8], input_payload, output_payload, payload_size));
@@ -1252,7 +1427,14 @@ smb_request (struct smb_server *server, int command, void * input_payload, const
* one packet to send.
*/
int
smb_trans2_request (struct smb_server *server, int command, int *data_len, int *param_len, char **data, char **param, int * error_ptr)
smb_trans2_request (
struct smb_server *server,
int command,
int *data_len,
int *param_len,
char **data,
char **param,
int * error_ptr)
{
unsigned char *buffer = server->transmit_buffer;
int sock_fd = server->mount_data.fd;
+3 -3
View File
@@ -42,9 +42,9 @@
/*****************************************************************************/
/* The network header files (e.g. AmiTCP, Miami) define this type,
* which clashes with how AmigaOS uses it. This moves it out of the
* way.
/* The <smb/smb.h> header file declares this, and it may be redefined
* in the TCP/IP stack header files. We try to avoid trouble by moving
* the type declaration out of the way...
*/
#define byte IGNORE_THIS