Move client_receive_smb to clientgen.c as a static, as proposed by Elrond.
[kai/samba.git] / source3 / libsmb / clientgen.c
index ec8d2e2bfc90942c5eb0e7dcfdd8704555ea142f..dee86b2b05d86b32c6c11ca5a4277e776aee79be 100644 (file)
@@ -1,6 +1,5 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 1.9.
+   Unix SMB/CIFS implementation.
    SMB client generic functions
    Copyright (C) Andrew Tridgell 1994-1998
    
@@ -32,12 +31,51 @@ int cli_set_port(struct cli_state *cli, int port)
        return port;
 }
 
+/****************************************************************************
+  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.
+****************************************************************************/
+
+static 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;
+}
+
+
 /****************************************************************************
 recv an smb
 ****************************************************************************/
 BOOL cli_receive_smb(struct cli_state *cli)
 {
        BOOL ret;
+
+       /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
+       if (cli->fd == -1) return False; 
+
  again:
        ret = client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
        
@@ -53,36 +91,41 @@ BOOL cli_receive_smb(struct cli_state *cli)
                                if (!cli->oplock_handler(cli, fnum, level)) return False;
                        }
                        /* try to prevent loops */
-                       CVAL(cli->inbuf,smb_com) = 0xFF;
+                       SCVAL(cli->inbuf,smb_com,0xFF);
                        goto again;
                }
        }
 
+        /* If the server is not responding, note that now */
+
+        if (!ret) {
+                close(cli->fd);
+                cli->fd = -1;
+        }
+
        return ret;
 }
 
 /****************************************************************************
-  send an smb to a fd and re-establish if necessary
+  send an smb to a fd.
 ****************************************************************************/
+
 BOOL cli_send_smb(struct cli_state *cli)
 {
        size_t len;
        size_t nwritten=0;
        ssize_t ret;
-       BOOL reestablished=False;
+
+       /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
+       if (cli->fd == -1) return False;
 
        len = smb_len(cli->outbuf) + 4;
 
        while (nwritten < len) {
                ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
-               if (ret <= 0 && errno == EPIPE && !reestablished) {
-                       if (cli_reestablish_connection(cli)) {
-                               reestablished = True;
-                               nwritten=0;
-                               continue;
-                       }
-               }
                if (ret <= 0) {
+                        close(cli->fd);
+                        cli->fd = -1;
                        DEBUG(0,("Error writing %d bytes to client. %d\n",
                                 (int)len,(int)ret));
                        return False;
@@ -130,7 +173,7 @@ void cli_setup_bcc(struct cli_state *cli, void *p)
 
 
 /****************************************************************************
-initialise a client structure
+initialise credentials of a client structure
 ****************************************************************************/
 void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr)
 {
@@ -154,6 +197,12 @@ struct cli_state *cli_initialise(struct cli_state *cli)
 {
         BOOL alloced_cli = False;
 
+       /* Check the effective uid - make sure we are not setuid */
+       if (is_setuid_root()) {
+               DEBUG(0,("libsmb based programs must *NOT* be setuid root.\n"));
+               return NULL;
+       }
+
        if (!cli) {
                cli = (struct cli_state *)malloc(sizeof(*cli));
                if (!cli)
@@ -183,10 +232,17 @@ struct cli_state *cli_initialise(struct cli_state *cli)
        cli->oplock_handler = cli_oplock_ack;
        cli->use_spnego = True;
 
+       /* Set the CLI_FORCE_DOSERR environment variable to test
+          client routines using DOS errors instead of STATUS32
+          ones.  This intended only as a temporary hack. */    
+       if (getenv("CLI_FORCE_DOSERR")) {
+               cli->force_dos_errors = True;
+       }
+
        if (!cli->outbuf || !cli->inbuf)
                 goto error;
 
-       if ((cli->mem_ctx = talloc_init()) == NULL)
+       if ((cli->mem_ctx = talloc_init_named("cli based talloc")) == NULL)
                 goto error;
 
        memset(cli->outbuf, 0, cli->bufsize);
@@ -195,6 +251,7 @@ struct cli_state *cli_initialise(struct cli_state *cli)
        cli->nt_pipe_fnum = 0;
 
        cli->initialised = 1;
+       cli->allocated = alloced_cli;
 
        return cli;
 
@@ -216,6 +273,7 @@ shutdown a client structure
 ****************************************************************************/
 void cli_shutdown(struct cli_state *cli)
 {
+       BOOL allocated;
        SAFE_FREE(cli->outbuf);
        SAFE_FREE(cli->inbuf);
 
@@ -224,13 +282,13 @@ void cli_shutdown(struct cli_state *cli)
        if (cli->mem_ctx)
                talloc_destroy(cli->mem_ctx);
 
-#ifdef WITH_SSL
-       if (cli->fd != -1)
-               sslutil_disconnect(cli->fd);
-#endif /* WITH_SSL */
        if (cli->fd != -1) 
                close(cli->fd);
-       memset(cli, 0, sizeof(*cli));
+       allocated = cli->allocated;
+       ZERO_STRUCTP(cli);
+       if (allocated) {
+               free(cli);
+       } 
 }