diff options
author | Andrew Tridgell <tridge@samba.org> | 1999-07-14 12:25:44 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1999-07-14 12:25:44 +0000 |
commit | b3e4e255ef819c1877a7c9ce0532035504a7fa90 (patch) | |
tree | ab628b7f41fb9fbbfea9db285aeb7f1dda58e3e0 | |
parent | c9954ef686a9e47240498f63918705b9b35d38bc (diff) | |
download | samba-b3e4e255ef819c1877a7c9ce0532035504a7fa90.tar.gz |
- cleanups in namequery code from 2.0
- use only one outstanding read until we find the multiplex bug
- add oplocks to client code (only used by smbtorture)
-rw-r--r-- | source/libsmb/clientgen.c | 186 | ||||
-rw-r--r-- | source/libsmb/namequery.c | 49 |
2 files changed, 163 insertions, 72 deletions
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c index cf2bfdd334c..ef7fc357471 100644 --- a/source/libsmb/clientgen.c +++ b/source/libsmb/clientgen.c @@ -28,6 +28,8 @@ extern int DEBUGLEVEL; extern pstring user_socket_options; +static void cli_process_oplock(struct cli_state *cli); + /* * Change the port number used to call on */ @@ -44,7 +46,23 @@ recv an smb ****************************************************************************/ static BOOL cli_receive_smb(struct cli_state *cli) { - return client_receive_smb(cli->fd,cli->inbuf,cli->timeout); + BOOL ret; + again: + ret = client_receive_smb(cli->fd,cli->inbuf,cli->timeout); + + if (ret && cli->use_oplocks) { + /* it might be an oplock break request */ + if (CVAL(cli->inbuf,smb_com) == SMBlockingX && + SVAL(cli->inbuf,smb_vwv6) == 0 && + SVAL(cli->inbuf,smb_vwv7) == 0) { + cli_process_oplock(cli); + /* try to prevent loops */ + CVAL(cli->inbuf,smb_com) = 0xFF; + goto again; + } + } + + return ret; } /**************************************************************************** @@ -80,6 +98,62 @@ static BOOL cli_send_smb(struct cli_state *cli) return True; } +/**************************************************************************** +setup basics in a outgoing packet +****************************************************************************/ +static void cli_setup_packet(struct cli_state *cli) +{ + cli->rap_error = 0; + cli->nt_error = 0; + SSVAL(cli->outbuf,smb_pid,cli->pid); + SSVAL(cli->outbuf,smb_uid,cli->vuid); + SSVAL(cli->outbuf,smb_mid,cli->mid); + if (cli->protocol > PROTOCOL_CORE) { + SCVAL(cli->outbuf,smb_flg,0x8); + SSVAL(cli->outbuf,smb_flg2,0x1); + } +} + + + +/**************************************************************************** +process an oplock break request from the server +****************************************************************************/ +static void cli_process_oplock(struct cli_state *cli) +{ + char *oldbuf = cli->outbuf; + pstring buf; + int fnum; + + fnum = SVAL(cli->inbuf,smb_vwv2); + + /* damn, we really need to keep a record of open files so we + can detect a oplock break and a close crossing on the + wire. for now this swallows the errors */ + if (fnum == 0) return; + + cli->outbuf = buf; + + memset(buf,'\0',smb_size); + set_message(buf,8,0,True); + + CVAL(buf,smb_com) = SMBlockingX; + SSVAL(buf,smb_tid, cli->cnum); + cli_setup_packet(cli); + SSVAL(buf,smb_vwv0,0xFF); + SSVAL(buf,smb_vwv1,0); + SSVAL(buf,smb_vwv2,fnum); + SSVAL(buf,smb_vwv3,2); /* oplock break ack */ + SIVAL(buf,smb_vwv4,0); /* timoeut */ + SSVAL(buf,smb_vwv6,0); /* unlockcount */ + SSVAL(buf,smb_vwv7,0); /* lockcount */ + + cli_send_smb(cli); + + cli->outbuf = oldbuf; +} + + /***************************************************** RAP error codes - a small start but will be extended. *******************************************************/ @@ -174,23 +248,6 @@ char *cli_errstr(struct cli_state *cli) return error_message; } -/**************************************************************************** -setup basics in a outgoing packet -****************************************************************************/ -static void cli_setup_packet(struct cli_state *cli) -{ - cli->rap_error = 0; - cli->nt_error = 0; - SSVAL(cli->outbuf,smb_pid,cli->pid); - SSVAL(cli->outbuf,smb_uid,cli->vuid); - SSVAL(cli->outbuf,smb_mid,cli->mid); - if (cli->protocol > PROTOCOL_CORE) { - SCVAL(cli->outbuf,smb_flg,0x8); - SSVAL(cli->outbuf,smb_flg2,0x1); - } -} - - /***************************************************************************** Convert a character pointer in a cli_call_api() response to a form we can use. This function contains code to prevent core dumps if the server returns @@ -1162,6 +1219,14 @@ int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode) SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN); SSVAL(cli->outbuf,smb_vwv5,0); SSVAL(cli->outbuf,smb_vwv8,openfn); + + if (cli->use_oplocks) { + /* if using oplocks then ask for a batch oplock via + core and extended methods */ + CVAL(cli->outbuf,smb_flg) |= + FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK; + SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6); + } p = smb_buf(cli->outbuf); pstrcpy(p,fname); @@ -1334,7 +1399,17 @@ size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t int total = -1; int issued=0; int received=0; - int mpx = MAX(cli->max_mux-1, 1); +/* + * There is a problem in this code when mpx is more than one. + * for some reason files can get corrupted when being read. + * Until we understand this fully I am serializing reads (one + * read/one reply) for now. JRA. + */ +#if 0 + int mpx = MAX(cli->max_mux-1, 1); +#else + int mpx = 1; +#endif int block = (cli->max_xmit - (smb_size+32)) & ~1023; int mid; int blocks = (size + (block-1)) / block; @@ -1492,39 +1567,50 @@ ssize_t cli_write(struct cli_state *cli, write to a file using a SMBwrite and not bypassing 0 byte writes ****************************************************************************/ ssize_t cli_smbwrite(struct cli_state *cli, - int fnum, char *buf, off_t offset, size_t size) + int fnum, char *buf, off_t offset, size_t size1) { char *p; + ssize_t total = 0; - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); - - set_message(cli->outbuf,5, 3 + size,True); + do { + size_t size = MIN(size1, cli->max_xmit - 48); + + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); - CVAL(cli->outbuf,smb_com) = SMBwrite; - SSVAL(cli->outbuf,smb_tid,cli->cnum); - cli_setup_packet(cli); + set_message(cli->outbuf,5, 3 + size,True); - SSVAL(cli->outbuf,smb_vwv0,fnum); - SSVAL(cli->outbuf,smb_vwv1,size); - SIVAL(cli->outbuf,smb_vwv2,offset); - SSVAL(cli->outbuf,smb_vwv4,0); - - p = smb_buf(cli->outbuf); - *p++ = 1; - SSVAL(p, 0, size); - memcpy(p+2, buf, size); + CVAL(cli->outbuf,smb_com) = SMBwrite; + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + SSVAL(cli->outbuf,smb_vwv0,fnum); + SSVAL(cli->outbuf,smb_vwv1,size); + SIVAL(cli->outbuf,smb_vwv2,offset); + SSVAL(cli->outbuf,smb_vwv4,0); + + p = smb_buf(cli->outbuf); + *p++ = 1; + SSVAL(p, 0, size); + memcpy(p+2, buf, size); + + cli_send_smb(cli); + if (!cli_receive_smb(cli)) { + return -1; + } + + if (CVAL(cli->inbuf,smb_rcls) != 0) { + return -1; + } - cli_send_smb(cli); - if (!cli_receive_smb(cli)) { - return False; - } + size = SVAL(cli->inbuf,smb_vwv0); + if (size == 0) break; - if (CVAL(cli->inbuf,smb_rcls) != 0) { - return -1; - } + size1 -= size; + total += size; + } while (size1); - return SVAL(cli->inbuf,smb_vwv0); + return total; } @@ -1538,7 +1624,7 @@ BOOL cli_getattrE(struct cli_state *cli, int fd, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,2,0,True); + set_message(cli->outbuf,1,0,True); CVAL(cli->outbuf,smb_com) = SMBgetattrE; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -1974,7 +2060,7 @@ static int interpret_long_filename(int level,char *p,file_info *finfo) p += 4; /* EA size */ p += 2; /* short name len? */ p += 24; /* short name? */ - StrnCpy(finfo->name,p,namelen); + StrnCpy(finfo->name,p,MIN(sizeof(finfo->name)-1,namelen)); return(ret); } return(SVAL(p,0)); @@ -2098,7 +2184,7 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, case 260: ff_resume_key =0; StrnCpy(mask,p+ff_lastname, - data_len-ff_lastname); + MIN(sizeof(mask)-1,data_len-ff_lastname)); break; case 1: pstrcpy(mask,p + ff_lastname + 1); @@ -2294,7 +2380,8 @@ BOOL cli_negprot(struct cli_state *cli) cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1); cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1); cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1); - cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60; + cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1); + cli->serverzone *= 60; /* this time arrives in real GMT */ cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1); memcpy(cli->cryptkey,smb_buf(cli->inbuf),8); @@ -2307,7 +2394,8 @@ BOOL cli_negprot(struct cli_state *cli) cli->sec_mode = SVAL(cli->inbuf,smb_vwv1); cli->max_xmit = SVAL(cli->inbuf,smb_vwv2); cli->sesskey = IVAL(cli->inbuf,smb_vwv6); - cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60; + cli->serverzone = SVALS(cli->inbuf,smb_vwv10); + cli->serverzone *= 60; /* this time is converted to GMT by make_unix_date */ cli->servertime = make_unix_date(cli->inbuf+smb_vwv8); cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0); diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c index 2244de4bdbf..ca0c7252e83 100644 --- a/source/libsmb/namequery.c +++ b/source/libsmb/namequery.c @@ -440,6 +440,9 @@ resolve via "bcast" method static BOOL resolve_bcast(const char *name, struct in_addr *return_ip, int name_type) { int sock, i; + struct in_addr *iplist = NULL; + int count; + int num_interfaces = iface_count(); /* * "bcast" means do a broadcast lookup on all the local interfaces. @@ -450,31 +453,28 @@ static BOOL resolve_bcast(const char *name, struct in_addr *return_ip, int name_ sock = open_socket_in( SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True ); - if (sock != -1) { - struct in_addr *iplist = NULL; - int count; - int num_interfaces = iface_count(); - set_socket_options(sock,"SO_BROADCAST"); - /* - * Lookup the name on all the interfaces, return on - * the first successful match. - */ - for( i = 0; i < num_interfaces; i++) { - struct in_addr sendto_ip; - /* Done this way to fix compiler error on IRIX 5.x */ - sendto_ip = *iface_bcast(*iface_n_ip(i)); - iplist = name_query(sock, name, name_type, True, - True, sendto_ip, &count, NULL); - if(iplist != NULL) { - *return_ip = iplist[0]; - free((char *)iplist); - close(sock); - return True; - } + if (sock == -1) return False; + + set_socket_options(sock,"SO_BROADCAST"); + /* + * Lookup the name on all the interfaces, return on + * the first successful match. + */ + for( i = 0; i < num_interfaces; i++) { + struct in_addr sendto_ip; + /* Done this way to fix compiler error on IRIX 5.x */ + sendto_ip = *iface_bcast(*iface_n_ip(i)); + iplist = name_query(sock, name, name_type, True, + True, sendto_ip, &count, NULL); + if(iplist != NULL) { + *return_ip = iplist[0]; + free((char *)iplist); + close(sock); + return True; } - close(sock); } + close(sock); return False; } @@ -607,7 +607,10 @@ BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type) for (i=0; pure_address && name[i]; i++) if (!(isdigit((int)name[i]) || name[i] == '.')) pure_address = False; - + + /* Check that a pure number is not misinterpreted as an IP */ + pure_address = pure_address && (strchr(name, '.') != NULL); + /* if it's in the form of an IP address then get the lib to interpret it */ if (pure_address) { return_ip->s_addr = inet_addr(name); |