/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
Samba utility functions
Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Tim Potter 2000-2001
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "includes.h"
-#ifdef WITH_SSL
-#include <openssl/ssl.h>
-#undef Realloc /* SSLeay defines this and samba has a function of this name */
-extern SSL *ssl;
-extern int sslFd;
-#endif /* WITH_SSL */
-
/* the last IP received from */
struct in_addr lastip;
BOOL is_a_socket(int fd)
{
- int v,l;
- l = sizeof(int);
- return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
+ int v,l;
+ l = sizeof(int);
+ return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
}
enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
-typedef struct smb_socket_option
-{
- char *name;
- int level;
- int option;
- int value;
- int opttype;
+typedef struct smb_socket_option {
+ char *name;
+ int level;
+ int option;
+ int value;
+ int opttype;
} smb_socket_option;
-smb_socket_option socket_options[] = {
+static const smb_socket_option socket_options[] = {
{"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
{"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
{"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
/****************************************************************************
Print socket options.
****************************************************************************/
+
static void print_socket_options(int s)
{
int value, vlen = 4;
- smb_socket_option *p = &socket_options[0];
+ const smb_socket_option *p = &socket_options[0];
for (; p->name != NULL; p++) {
if (getsockopt(s, p->level, p->option, (void *)&value, &vlen) == -1) {
memset((char *)&sock,'\0',socklen);
memset((char *)&lastip,'\0',sizeof(lastip));
- ret = (ssize_t)recvfrom(fd,buf,len,0,(struct sockaddr *)&sock,&socklen);
+ ret = (ssize_t)sys_recvfrom(fd,buf,len,0,(struct sockaddr *)&sock,&socklen);
if (ret <= 0) {
DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno)));
return(0);
return(ret);
}
-/****************************************************************************
- Read data from a socket with a timout in msec.
- mincount = if timeout, minimum to read before returning
- maxcount = number to be read.
- time_out = timeout in milliseconds
-****************************************************************************/
-
-static ssize_t read_socket_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out)
+/*******************************************************************
+ checks if read data is outstanding.
+ ********************************************************************/
+static int read_data_outstanding(int fd, unsigned int time_out)
{
- fd_set fds;
- int selrtn;
- ssize_t readret;
- size_t nread = 0;
- struct timeval timeout;
-
- /* just checking .... */
- if (maxcnt <= 0)
- return(0);
-
- smb_read_error = 0;
-
- /* Blocking read */
- if (time_out <= 0) {
- if (mincnt == 0) mincnt = maxcnt;
-
- while (nread < mincnt) {
-#ifdef WITH_SSL
- if(fd == sslFd){
- readret = SSL_read(ssl, buf + nread, maxcnt - nread);
- }else{
- readret = read(fd, buf + nread, maxcnt - nread);
- }
-#else /* WITH_SSL */
- readret = read(fd, buf + nread, maxcnt - nread);
-#endif /* WITH_SSL */
-
- if (readret == 0) {
- DEBUG(5,("read_socket_with_timeout: blocking read. EOF from client.\n"));
- smb_read_error = READ_EOF;
- return -1;
- }
+ int selrtn;
+ fd_set fds;
+ struct timeval timeout;
- if (readret == -1) {
- DEBUG(0,("read_socket_with_timeout: read error = %s.\n", strerror(errno) ));
- smb_read_error = READ_ERROR;
- return -1;
- }
- nread += readret;
- }
- return((ssize_t)nread);
- }
-
- /* Most difficult - timeout read */
- /* If this is ever called on a disk file and
- mincnt is greater then the filesize then
- system performance will suffer severely as
- select always returns true on disk files */
-
- /* Set initial timeout */
- timeout.tv_sec = (time_t)(time_out / 1000);
- timeout.tv_usec = (long)(1000 * (time_out % 1000));
-
- for (nread=0; nread < mincnt; ) {
- FD_ZERO(&fds);
- FD_SET(fd,&fds);
-
- selrtn = sys_select_intr(fd+1,&fds,&timeout);
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
- /* Check if error */
- if(selrtn == -1) {
- /* something is wrong. Maybe the socket is dead? */
- DEBUG(0,("read_socket_with_timeout: timeout read. select error = %s.\n", strerror(errno) ));
- smb_read_error = READ_ERROR;
- return -1;
- }
+ timeout.tv_sec = (time_t) (time_out / 1000);
+ timeout.tv_usec = (long)(1000 * (time_out % 1000));
- /* Did we timeout ? */
- if (selrtn == 0) {
- DEBUG(10,("read_socket_with_timeout: timeout read. select timed out.\n"));
- smb_read_error = READ_TIMEOUT;
- return -1;
- }
-
-#ifdef WITH_SSL
- if(fd == sslFd){
- readret = SSL_read(ssl, buf + nread, maxcnt - nread);
- }else{
- readret = read(fd, buf + nread, maxcnt - nread);
- }
-#else /* WITH_SSL */
- readret = read(fd, buf+nread, maxcnt-nread);
-#endif /* WITH_SSL */
-
- if (readret == 0) {
- /* we got EOF on the file descriptor */
- DEBUG(5,("read_socket_with_timeout: timeout read. EOF from client.\n"));
- smb_read_error = READ_EOF;
- return -1;
- }
+ selrtn = sys_select_intr(fd + 1, &fds, NULL, NULL, &timeout);
- if (readret == -1) {
- /* the descriptor is probably dead */
- DEBUG(0,("read_socket_with_timeout: timeout read. read error = %s.\n", strerror(errno) ));
- smb_read_error = READ_ERROR;
- return -1;
- }
-
- nread += readret;
- }
-
- /* Return the number we got */
- return((ssize_t)nread);
+ if (selrtn <= 0)
+ {
+ return selrtn;
+ }
+ return FD_ISSET(fd, &fds) ? 1 : 0;
}
/****************************************************************************
- Read data from a fd with a timout in msec.
+ Read data from a socket with a timout in msec.
mincount = if timeout, minimum to read before returning
maxcount = number to be read.
time_out = timeout in milliseconds
****************************************************************************/
-ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out)
+static ssize_t read_socket_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out)
{
- fd_set fds;
- int selrtn;
- ssize_t readret;
- size_t nread = 0;
- struct timeval timeout;
-
- /* just checking .... */
- if (maxcnt <= 0)
- return(0);
-
- /* Blocking read */
- if (time_out <= 0) {
- if (mincnt == 0) mincnt = maxcnt;
-
- while (nread < mincnt) {
-#ifdef WITH_SSL
- if(fd == sslFd){
- readret = SSL_read(ssl, buf + nread, maxcnt - nread);
- }else{
- readret = read(fd, buf + nread, maxcnt - nread);
- }
-#else /* WITH_SSL */
- readret = read(fd, buf + nread, maxcnt - nread);
-#endif /* WITH_SSL */
-
- if (readret <= 0)
- return readret;
-
- nread += readret;
- }
- return((ssize_t)nread);
- }
-
- /* Most difficult - timeout read */
- /* If this is ever called on a disk file and
- mincnt is greater then the filesize then
- system performance will suffer severely as
- select always returns true on disk files */
-
- /* Set initial timeout */
- timeout.tv_sec = (time_t)(time_out / 1000);
- timeout.tv_usec = (long)(1000 * (time_out % 1000));
-
- for (nread=0; nread < mincnt; ) {
- FD_ZERO(&fds);
- FD_SET(fd,&fds);
-
- selrtn = sys_select_intr(fd+1,&fds,&timeout);
-
- if(selrtn <= 0)
- return selrtn;
-
-#ifdef WITH_SSL
- if(fd == sslFd){
- readret = SSL_read(ssl, buf + nread, maxcnt - nread);
- }else{
- readret = read(fd, buf + nread, maxcnt - nread);
- }
-#else /* WITH_SSL */
- readret = read(fd, buf+nread, maxcnt-nread);
-#endif /* WITH_SSL */
-
- if (readret <= 0)
- return readret;
-
- nread += readret;
- }
-
- /* Return the number we got */
- return((ssize_t)nread);
+ fd_set fds;
+ int selrtn;
+ ssize_t readret;
+ size_t nread = 0;
+ struct timeval timeout;
+
+ /* just checking .... */
+ if (maxcnt <= 0)
+ return(0);
+
+ smb_read_error = 0;
+
+ /* Blocking read */
+ if (time_out <= 0) {
+ if (mincnt == 0) mincnt = maxcnt;
+
+ while (nread < mincnt) {
+ readret = sys_read(fd, buf + nread, maxcnt - nread);
+
+ if (readret == 0) {
+ DEBUG(5,("read_socket_with_timeout: blocking read. EOF from client.\n"));
+ smb_read_error = READ_EOF;
+ return -1;
+ }
+
+ if (readret == -1) {
+ DEBUG(0,("read_socket_with_timeout: read error = %s.\n", strerror(errno) ));
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+ nread += readret;
+ }
+ return((ssize_t)nread);
+ }
+
+ /* Most difficult - timeout read */
+ /* If this is ever called on a disk file and
+ mincnt is greater then the filesize then
+ system performance will suffer severely as
+ select always returns true on disk files */
+
+ /* Set initial timeout */
+ timeout.tv_sec = (time_t)(time_out / 1000);
+ timeout.tv_usec = (long)(1000 * (time_out % 1000));
+
+ for (nread=0; nread < mincnt; ) {
+ FD_ZERO(&fds);
+ FD_SET(fd,&fds);
+
+ selrtn = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout);
+
+ /* Check if error */
+ if (selrtn == -1) {
+ /* something is wrong. Maybe the socket is dead? */
+ DEBUG(0,("read_socket_with_timeout: timeout read. select error = %s.\n", strerror(errno) ));
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+
+ /* Did we timeout ? */
+ if (selrtn == 0) {
+ DEBUG(10,("read_socket_with_timeout: timeout read. select timed out.\n"));
+ smb_read_error = READ_TIMEOUT;
+ return -1;
+ }
+
+ readret = sys_read(fd, buf+nread, maxcnt-nread);
+
+ if (readret == 0) {
+ /* we got EOF on the file descriptor */
+ DEBUG(5,("read_socket_with_timeout: timeout read. EOF from client.\n"));
+ smb_read_error = READ_EOF;
+ return -1;
+ }
+
+ if (readret == -1) {
+ /* the descriptor is probably dead */
+ DEBUG(0,("read_socket_with_timeout: timeout read. read error = %s.\n", strerror(errno) ));
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+
+ nread += readret;
+ }
+
+ /* Return the number we got */
+ return (ssize_t)nread;
}
/****************************************************************************
-send a keepalive packet (rfc1002)
+ Read data from a fd with a timout in msec.
+ mincount = if timeout, minimum to read before returning
+ maxcount = number to be read.
+ time_out = timeout in milliseconds
****************************************************************************/
-BOOL send_keepalive(int client)
+ssize_t read_with_timeout(int fd, char *buf, size_t mincnt, size_t maxcnt,
+ unsigned int time_out)
{
- unsigned char buf[4];
-
- buf[0] = SMBkeepalive;
- buf[1] = buf[2] = buf[3] = 0;
-
- return(write_socket_data(client,(char *)buf,4) == 4);
+ ssize_t readret;
+ size_t nread = 0;
+
+ /* just checking .... */
+ if (maxcnt <= 0)
+ return(0);
+
+ /* Blocking read */
+ if (time_out <= 0) {
+ if (mincnt == 0) mincnt = maxcnt;
+
+ while (nread < mincnt) {
+ readret = sys_read(fd, buf + nread, maxcnt - nread);
+
+ if (readret <= 0)
+ return readret;
+
+ nread += readret;
+ }
+ return((ssize_t)nread);
+ }
+
+ /* Most difficult - timeout read */
+ /* If this is ever called on a disk file and
+ mincnt is greater then the filesize then
+ system performance will suffer severely as
+ select always returns true on disk files */
+
+ for (nread=0; nread < mincnt; ) {
+ int selrtn = read_data_outstanding(fd, time_out);
+
+ if(selrtn <= 0)
+ return selrtn;
+
+ readret = sys_read(fd, buf+nread, maxcnt-nread);
+
+ if (readret <= 0)
+ return readret;
+
+ nread += readret;
+ }
+
+ /* Return the number we got */
+ return((ssize_t)nread);
}
/****************************************************************************
ssize_t read_data(int fd,char *buffer,size_t N)
{
- ssize_t ret;
- size_t total=0;
+ ssize_t ret;
+ size_t total=0;
- smb_read_error = 0;
-
- while (total < N)
- {
-#ifdef WITH_SSL
- if(fd == sslFd){
- ret = SSL_read(ssl, buffer + total, N - total);
- }else{
- ret = read(fd,buffer + total,N - total);
- }
-#else /* WITH_SSL */
- ret = read(fd,buffer + total,N - total);
-#endif /* WITH_SSL */
-
- if (ret == 0)
- {
- DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));
- smb_read_error = READ_EOF;
- return 0;
- }
- if (ret == -1)
- {
- DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));
- smb_read_error = READ_ERROR;
- return -1;
- }
- total += ret;
- }
- return (ssize_t)total;
+ smb_read_error = 0;
+
+ while (total < N) {
+ ret = sys_read(fd,buffer + total,N - total);
+
+ if (ret == 0) {
+ DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));
+ smb_read_error = READ_EOF;
+ return 0;
+ }
+
+ if (ret == -1) {
+ DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+ total += ret;
+ }
+ return (ssize_t)total;
}
/****************************************************************************
static ssize_t read_socket_data(int fd,char *buffer,size_t N)
{
- ssize_t ret;
- size_t total=0;
+ ssize_t ret;
+ size_t total=0;
- smb_read_error = 0;
-
- while (total < N)
- {
-#ifdef WITH_SSL
- if(fd == sslFd){
- ret = SSL_read(ssl, buffer + total, N - total);
- }else{
- ret = read(fd,buffer + total,N - total);
- }
-#else /* WITH_SSL */
- ret = read(fd,buffer + total,N - total);
-#endif /* WITH_SSL */
-
- if (ret == 0)
- {
- DEBUG(10,("read_socket_data: recv of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));
- smb_read_error = READ_EOF;
- return 0;
- }
- if (ret == -1)
- {
- DEBUG(0,("read_socket_data: recv failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));
- smb_read_error = READ_ERROR;
- return -1;
- }
- total += ret;
- }
- return (ssize_t)total;
+ smb_read_error = 0;
+
+ while (total < N) {
+ ret = sys_read(fd,buffer + total,N - total);
+
+ if (ret == 0) {
+ DEBUG(10,("read_socket_data: recv of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));
+ smb_read_error = READ_EOF;
+ return 0;
+ }
+
+ if (ret == -1) {
+ DEBUG(0,("read_socket_data: recv failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+ total += ret;
+ }
+ return (ssize_t)total;
}
/****************************************************************************
ssize_t write_data(int fd,char *buffer,size_t N)
{
- size_t total=0;
- ssize_t ret;
-
- while (total < N)
- {
-#ifdef WITH_SSL
- if(fd == sslFd){
- ret = SSL_write(ssl,buffer + total,N - total);
- }else{
- ret = write(fd,buffer + total,N - total);
- }
-#else /* WITH_SSL */
- ret = write(fd,buffer + total,N - total);
-#endif /* WITH_SSL */
-
- if (ret == -1) {
- DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) ));
- return -1;
- }
- if (ret == 0) return total;
+ size_t total=0;
+ ssize_t ret;
- total += ret;
- }
- return (ssize_t)total;
+ while (total < N) {
+ ret = sys_write(fd,buffer + total,N - total);
+
+ if (ret == -1) {
+ DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) ));
+ return -1;
+ }
+ if (ret == 0)
+ return total;
+
+ total += ret;
+ }
+ return (ssize_t)total;
}
/****************************************************************************
Write data to a socket - use send rather than write.
****************************************************************************/
-ssize_t write_socket_data(int fd,char *buffer,size_t N)
+static ssize_t write_socket_data(int fd,char *buffer,size_t N)
{
- size_t total=0;
- ssize_t ret;
-
- while (total < N)
- {
-#ifdef WITH_SSL
- if(fd == sslFd){
- ret = SSL_write(ssl,buffer + total,N - total);
- }else{
- ret = send(fd,buffer + total,N - total, 0);
- }
-#else /* WITH_SSL */
- ret = send(fd,buffer + total,N - total,0);
-#endif /* WITH_SSL */
-
- if (ret == -1) {
- DEBUG(0,("write_socket_data: write failure. Error = %s\n", strerror(errno) ));
- return -1;
- }
- if (ret == 0) return total;
+ size_t total=0;
+ ssize_t ret;
- total += ret;
- }
- return (ssize_t)total;
+ while (total < N) {
+ ret = sys_send(fd,buffer + total,N - total,0);
+
+ if (ret == -1) {
+ DEBUG(0,("write_socket_data: write failure. Error = %s\n", strerror(errno) ));
+ return -1;
+ }
+ if (ret == 0)
+ return total;
+
+ total += ret;
+ }
+ return (ssize_t)total;
}
/****************************************************************************
ssize_t write_socket(int fd,char *buf,size_t len)
{
- ssize_t ret=0;
+ ssize_t ret=0;
- DEBUG(6,("write_socket(%d,%d)\n",fd,(int)len));
- ret = write_socket_data(fd,buf,len);
+ DEBUG(6,("write_socket(%d,%d)\n",fd,(int)len));
+ ret = write_socket_data(fd,buf,len);
- DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,(int)len,(int)ret));
- if(ret <= 0)
- DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n",
- (int)len, fd, strerror(errno) ));
+ DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,(int)len,(int)ret));
+ if(ret <= 0)
+ DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n",
+ (int)len, fd, strerror(errno) ));
- return(ret);
+ return(ret);
}
+/****************************************************************************
+send a keepalive packet (rfc1002)
+****************************************************************************/
+
+BOOL send_keepalive(int client)
+{
+ unsigned char buf[4];
+
+ buf[0] = SMBkeepalive;
+ buf[1] = buf[2] = buf[3] = 0;
+
+ return(write_socket_data(client,(char *)buf,4) == 4);
+}
+
+
/****************************************************************************
read 4 bytes of a smb packet and return the smb length of the packet
store the result in the buffer
static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int timeout)
{
- ssize_t len=0;
- int msg_type;
- BOOL ok = False;
+ ssize_t len=0;
+ int msg_type;
+ BOOL ok = False;
- while (!ok)
- {
- if (timeout > 0)
- ok = (read_socket_with_timeout(fd,inbuf,4,4,timeout) == 4);
- else
- ok = (read_socket_data(fd,inbuf,4) == 4);
+ while (!ok) {
+ if (timeout > 0)
+ ok = (read_socket_with_timeout(fd,inbuf,4,4,timeout) == 4);
+ else
+ ok = (read_socket_data(fd,inbuf,4) == 4);
- if (!ok)
- return(-1);
+ if (!ok)
+ return(-1);
- len = smb_len(inbuf);
- msg_type = CVAL(inbuf,0);
+ len = smb_len(inbuf);
+ msg_type = CVAL(inbuf,0);
- if (msg_type == SMBkeepalive)
- DEBUG(5,("Got keepalive packet\n"));
- }
+ if (msg_type == SMBkeepalive)
+ DEBUG(5,("Got keepalive packet\n"));
+ }
- DEBUG(10,("got smb length of %d\n",len));
+ DEBUG(10,("got smb length of %d\n",len));
- return(len);
+ return(len);
}
/****************************************************************************
ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout)
{
- ssize_t len;
+ ssize_t len;
- for(;;)
- {
- len = read_smb_length_return_keepalive(fd, inbuf, timeout);
+ for(;;) {
+ len = read_smb_length_return_keepalive(fd, inbuf, timeout);
- if(len < 0)
- return len;
+ if(len < 0)
+ return len;
- /* Ignore session keepalives. */
- if(CVAL(inbuf,0) != SMBkeepalive)
- break;
- }
+ /* Ignore session keepalives. */
+ if(CVAL(inbuf,0) != SMBkeepalive)
+ break;
+ }
- DEBUG(10,("read_smb_length: got smb length of %d\n",len));
+ DEBUG(10,("read_smb_length: got smb length of %d\n",len));
- return len;
+ return len;
}
/****************************************************************************
len = read_smb_length_return_keepalive(fd,buffer,timeout);
if (len < 0) {
DEBUG(10,("receive_smb: length < 0!\n"));
- return(False);
+
+ /*
+ * Correct fix. smb_read_error may have already been
+ * set. Only set it here if not already set. Global
+ * variables still suck :-). JRA.
+ */
+
+ if (smb_read_error == 0)
+ smb_read_error = READ_ERROR;
+ return False;
}
/*
* A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
- * of header. Don't print the error if this fits.... JRA.
+ * of header. Don't print the error if this fits.... JRA.
*/
if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
DEBUG(0,("Invalid packet length! (%d bytes).\n",len));
if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) {
- smb_read_error = READ_ERROR;
+
+ /*
+ * Correct fix. smb_read_error may have already been
+ * set. Only set it here if not already set. Global
+ * variables still suck :-). JRA.
+ */
+
+ if (smb_read_error == 0)
+ smb_read_error = READ_ERROR;
return False;
}
}
if(len > 0) {
ret = read_socket_data(fd,buffer+4,len);
if (ret != len) {
- smb_read_error = READ_ERROR;
+ if (smb_read_error == 0)
+ smb_read_error = READ_ERROR;
return False;
}
}
return(True);
}
-/****************************************************************************
- read an smb from a fd ignoring all keepalive packets. Note that the buffer
- *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN.
- The timeout is in milliseconds
-
- This is exactly the same as receive_smb except that it never returns
- a session keepalive packet (just as receive_smb used to do).
- receive_smb was changed to return keepalives as the oplock processing means this call
- should never go into a blocking read.
-****************************************************************************/
-
-BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
-{
- BOOL ret;
-
- for(;;)
- {
- ret = receive_smb(fd, buffer, timeout);
-
- if (!ret)
- {
- DEBUG(10,("client_receive_smb failed\n"));
- show_msg(buffer);
- return ret;
- }
-
- /* Ignore session keepalive packets. */
- if(CVAL(buffer,0) != SMBkeepalive)
- break;
- }
- show_msg(buffer);
- return ret;
-}
-
/****************************************************************************
send an smb to a fd
****************************************************************************/
return True;
}
-/****************************************************************************
-send a single packet to a port on another machine
-****************************************************************************/
-
-BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
-{
- BOOL ret;
- int out_fd;
- struct sockaddr_in sock_out;
-
- /* create a socket to write to */
- out_fd = socket(AF_INET, type, 0);
- if (out_fd == -1)
- {
- DEBUG(0,("socket failed"));
- return False;
- }
-
- /* set the address and port */
- memset((char *)&sock_out,'\0',sizeof(sock_out));
- putip((char *)&sock_out.sin_addr,(char *)&ip);
- sock_out.sin_port = htons( port );
- sock_out.sin_family = AF_INET;
-
- if (DEBUGLEVEL > 0)
- DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n",
- len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM"));
-
- /* send it */
- ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
-
- if (!ret)
- DEBUG(0,("Packet send to %s(%d) failed ERRNO=%s\n",
- inet_ntoa(ip),port,strerror(errno)));
-
- close(out_fd);
- return(ret);
-}
-
/****************************************************************************
Open a socket of the specified type, port, and address for incoming data.
****************************************************************************/
if( setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)) == -1 ) {
if( DEBUGLVL( dlevel ) ) {
dbgtext( "open_socket_in(): setsockopt: ");
- dbgtext( "SO_REUSEPORT = %d ", val?"True":"False" );
+ dbgtext( "SO_REUSEPORT = %s ", val?"True":"False" );
dbgtext( "on port %d failed ", port );
dbgtext( "with error = %s\n", strerror(errno) );
}
/* now we've got a socket - we need to bind it */
if( bind( res, (struct sockaddr *)&sock, sizeof(sock) ) == -1 ) {
- if( DEBUGLVL(dlevel) && (port == SMB_PORT || port == NMB_PORT) ) {
+ if( DEBUGLVL(dlevel) && (port == SMB_PORT1 || port == SMB_PORT2 || port == NMB_PORT) ) {
dbgtext( "bind failed on port %d ", port );
dbgtext( "socket_addr = %s.\n", inet_ntoa( sock.sin_addr ) );
dbgtext( "Error = %s\n", strerror(errno) );
return( -1 );
}
- DEBUG( 3, ( "bind succeeded on port %d\n", port ) );
+ DEBUG( 10, ( "bind succeeded on port %d\n", port ) );
return( res );
}
char *client_name(void)
{
- return get_socket_name(client_fd);
+ return get_socket_name(client_fd,False);
}
char *client_addr(void)
/* Look up the host address in the address list we just got. */
for (i = 0; hp->h_addr_list[i]; i++) {
- if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
+ if (memcmp(hp->h_addr_list[i], (char *) & addr, sizeof(addr)) == 0)
return True;
}
/*******************************************************************
return the DNS name of the remote end of a socket
******************************************************************/
-char *get_socket_name(int fd)
+char *get_socket_name(int fd, BOOL force_lookup)
{
static pstring name_buf;
static fstring addr_buf;
situations won't work because many networks don't link dhcp
with dns. To avoid the delay we avoid the lookup if
possible */
- if (!lp_hostname_lookups()) {
+ if (!lp_hostname_lookups() && (force_lookup == False)) {
return get_socket_addr(fd);
}
return addr_buf;
}
+
/*******************************************************************
- opens and connects to a unix pipe socket
+ Create protected unix domain socket.
+
+ some unixen cannot set permissions on a ux-dom-sock, so we
+ have to make sure that the directory contains the protection
+ permissions, instead.
******************************************************************/
-int open_pipe_sock(char *path)
+int create_pipe_sock(const char *socket_dir,
+ const char *socket_name,
+ mode_t dir_perms)
{
- int sock;
- struct sockaddr_un sa;
-
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
-
- if (sock < 0)
- {
- DEBUG(0, ("unix socket open failed\n"));
- return sock;
- }
-
- ZERO_STRUCT(sa);
- sa.sun_family = AF_UNIX;
- safe_strcpy(sa.sun_path, path, sizeof(sa.sun_path)-1);
-
- DEBUG(10, ("socket open succeeded. file name: %s\n", sa.sun_path));
-
- if (connect(sock, (struct sockaddr*) &sa, sizeof(sa)) < 0)
- {
- DEBUG(0,("socket connect to %s failed\n", sa.sun_path));
- close(sock);
- return -1;
- }
-
- return sock;
+#ifdef HAVE_UNIXSOCKET
+ struct sockaddr_un sunaddr;
+ struct stat st;
+ int sock;
+ mode_t old_umask;
+ pstring path;
+
+ /* Create the socket directory or reuse the existing one */
+
+ if (lstat(socket_dir, &st) == -1) {
+
+ if (errno == ENOENT) {
+
+ /* Create directory */
+
+ if (mkdir(socket_dir, dir_perms) == -1) {
+ DEBUG(0, ("error creating socket directory "
+ "%s: %s\n", socket_dir,
+ strerror(errno)));
+ return -1;
+ }
+
+ } else {
+
+ DEBUG(0, ("lstat failed on socket directory %s: %s\n",
+ socket_dir, strerror(errno)));
+ return -1;
+ }
+
+ } else {
+
+ /* Check ownership and permission on existing directory */
+
+ if (!S_ISDIR(st.st_mode)) {
+ DEBUG(0, ("socket directory %s isn't a directory\n",
+ socket_dir));
+ return -1;
+ }
+
+ if ((st.st_uid != sec_initial_uid()) ||
+ ((st.st_mode & 0777) != dir_perms)) {
+ DEBUG(0, ("invalid permissions on socket directory "
+ "%s\n", socket_dir));
+ return -1;
+ }
+ }
+
+ /* Create the socket file */
+
+ old_umask = umask(0);
+
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+
+ if (sock == -1) {
+ perror("socket");
+ umask(old_umask);
+ return -1;
+ }
+
+ snprintf(path, sizeof(path), "%s/%s", socket_dir, socket_name);
+
+ unlink(path);
+ memset(&sunaddr, 0, sizeof(sunaddr));
+ sunaddr.sun_family = AF_UNIX;
+ safe_strcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)-1);
+
+ if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) {
+ DEBUG(0, ("bind failed on pipe socket %s: %s\n",
+ path,
+ strerror(errno)));
+ close(sock);
+ umask(old_umask);
+ return -1;
+ }
+
+ if (listen(sock, 5) == -1) {
+ DEBUG(0, ("listen failed on pipe socket %s: %s\n",
+ path,
+ strerror(errno)));
+ close(sock);
+ umask(old_umask);
+ return -1;
+ }
+
+ umask(old_umask);
+
+ /* Success! */
+
+ return sock;
+#else
+ DEBUG(0, ("create_pipe_sock: No Unix sockets on this system\n"));
+ return -1;
+#endif /* HAVE_UNIXSOCKET */
}
/*******************************************************************