cool! created higher-order function table for agent redirection.
authorLuke Leighton <lkcl@samba.org>
Sat, 4 Dec 1999 21:55:39 +0000 (21:55 +0000)
committerLuke Leighton <lkcl@samba.org>
Sat, 4 Dec 1999 21:55:39 +0000 (21:55 +0000)
(This used to be commit 7bb2e55d0d3a00a97bba99ebed722a4adf84093c)

source3/Makefile.in
source3/include/proto.h
source3/include/smb.h
source3/include/vagent.h [new file with mode: 0644]
source3/lib/vagent.c [new file with mode: 0644]
source3/utils/smb-agent.c

index cb102e06073cf2d5a21ad491503854e4cfb41d66..6984baf7c3c3759a791b836b3be1d327277a2905 100644 (file)
@@ -113,6 +113,7 @@ LIB_OBJ = lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \
                lib/util_file.o mem_man/mem_man.o \
                lib/util_sock.o lib/unix_sec_ctxt.o \
                lib/util_array.o \
+               lib/vagent.o \
                lib/util_hnd.o
 
 UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
index 24dfd6ed1a87eb7a330eb8d7abecc638b2083a4f..5e423e37266aa6f2b3a7d0982be9c720c49c2fad 100644 (file)
@@ -138,6 +138,12 @@ BOOL allow_access(char *deny_list,char *allow_list,
                  char *cname,char *caddr);
 BOOL check_access(int sock, char *allow_list, char *deny_list);
 
+/*The following definitions come from  lib/agent.c  */
+
+void init_sock_redir(struct vagent_ops*va);
+void free_sock_redir(struct vagent_ops*va);
+void start_agent(struct vagent_ops *va);
+
 /*The following definitions come from  lib/bitmap.c  */
 
 struct bitmap *bitmap_allocate(int n);
index 8adfa5e690823588cd9ec2d5dd112ca5f000afe3..d4d2f6712a1ff4f08d89277979bead02de6d2839 100644 (file)
@@ -550,6 +550,9 @@ typedef struct
 
 #include "vfs.h"
 
+
+#include "vagent.h"
+
 typedef struct connection_struct
 {
        struct connection_struct *next, *prev;
diff --git a/source3/include/vagent.h b/source3/include/vagent.h
new file mode 100644 (file)
index 0000000..19bb976
--- /dev/null
@@ -0,0 +1,51 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+   Vagent structures and parameters
+   Copyright (C) Luke Kenneth Casson Leighton 1999
+   
+   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
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _VAGENT_H
+#define _VAGENT_H
+
+/* Vagent operations structure */
+
+struct sock_redir
+{
+       int c;
+       int s;
+       int c_id;
+       int s_id;
+       void *n;
+};
+
+struct vagent_ops
+{
+       void (*free_sock)(void* sock);
+       int (*get_agent_sock)(void* id);
+
+       BOOL (*process_cli_sock)(struct sock_redir **socks, uint32 num_socks,
+                               struct sock_redir *sock);
+       BOOL (*process_srv_sock)(struct sock_redir **socks, uint32 num_socks,
+                               int fd);
+
+       void* id;
+       struct sock_redir **socks;
+       uint32 num_socks;
+};
+
+#endif /* _VAGENT_H */
diff --git a/source3/lib/vagent.c b/source3/lib/vagent.c
new file mode 100644 (file)
index 0000000..96df03e
--- /dev/null
@@ -0,0 +1,242 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 2
+   SMB agent/socket plugin
+   Copyright (C) Andrew Tridgell 1999
+   
+   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
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "smb.h"
+
+extern int DEBUGLEVEL;
+
+
+/****************************************************************************
+terminate socket connection
+****************************************************************************/
+static void sock_redir_free(struct vagent_ops *va, struct sock_redir *sock)
+{
+       if (sock->c != -1)
+       {
+               close(sock->c);
+               sock->c = -1;
+       }
+       if (sock->n != NULL)
+       {
+               va->free_sock(sock->n);
+               sock->n = NULL;
+       }
+       free(sock);
+}
+
+/****************************************************************************
+free a sockent array
+****************************************************************************/
+static void free_sock_array(struct vagent_ops*va)
+{
+       void(*fn)(void*) = (void(*)(void*))&va->free_sock;
+       free_void_array(va->num_socks, (void**)va->socks, *fn);
+}
+
+/****************************************************************************
+add a sockent state to the array
+****************************************************************************/
+static struct sock_redir* add_sock_to_array(uint32 *len,
+                               struct sock_redir ***array,
+                               struct sock_redir *sock)
+{
+       int i;
+       for (i = 0; i < (*len); i++)
+       {
+               if ((*array)[i] == NULL)
+               {
+                       (*array)[i] = sock;
+                       return sock;
+               }
+       }
+
+       return (struct sock_redir*)add_item_to_array(len,
+                            (void***)array, (void*)sock);
+                               
+}
+
+/****************************************************************************
+initiate sockent array
+****************************************************************************/
+void init_sock_redir(struct vagent_ops*va)
+{
+       va->socks = NULL;
+       va->num_socks = 0;
+}
+
+/****************************************************************************
+terminate sockent array
+****************************************************************************/
+void free_sock_redir(struct vagent_ops*va)
+{
+       free_sock_array(va);
+       init_sock_redir(va);
+}
+
+/****************************************************************************
+create a new sockent state from user credentials
+****************************************************************************/
+static struct sock_redir *sock_redir_get(struct vagent_ops *va, int fd)
+{
+       struct sock_redir *sock = (struct sock_redir*)malloc(sizeof(*sock));
+
+       if (sock == NULL)
+       {
+               return NULL;
+       }
+
+       ZERO_STRUCTP(sock);
+
+       sock->c = fd;
+       sock->n = NULL;
+
+       DEBUG(10,("sock_redir_get:\tfd:\t%d\n", fd));
+
+       return sock;
+}
+/****************************************************************************
+init sock state
+****************************************************************************/
+static void sock_add(struct vagent_ops *va, int fd)
+{
+       struct sock_redir *sock;
+       sock = sock_redir_get(va, fd);
+       if (sock != NULL)
+       {
+               add_sock_to_array(&va->num_socks, &va->socks, sock);
+       }
+}
+
+/****************************************************************************
+delete a sockent state
+****************************************************************************/
+static BOOL sock_del(struct vagent_ops *va, int fd)
+{
+       int i;
+
+       for (i = 0; i < va->num_socks; i++)
+       {
+               if (va->socks[i] == NULL) continue;
+               if (va->socks[i]->c == fd) 
+               {
+                       sock_redir_free(va, va->socks[i]);
+                       va->socks[i] = NULL;
+                       return True;
+               }
+       }
+
+       return False;
+}
+
+void start_agent(struct vagent_ops *va)
+{
+       int s, c;
+
+       s = va->get_agent_sock(va->id);
+
+       while (1)
+       {
+               int i;
+               fd_set fds;
+               int num;
+               struct sockaddr_un addr;
+               int in_addrlen = sizeof(addr);
+               int maxfd = s;
+               
+               FD_ZERO(&fds);
+               FD_SET(s, &fds);
+
+               for (i = 0; i < va->num_socks; i++)
+               {
+                       if (va->socks[i] != NULL)
+                       {
+                               int fd = va->socks[i]->c;
+                               FD_SET(fd, &fds);
+                               maxfd = MAX(maxfd, fd);
+
+                               if (va->socks[i]->n != NULL)
+                               {
+                                       fd = va->socks[i]->s;
+                                       FD_SET(fd, &fds);
+                                       maxfd = MAX(fd, maxfd);
+                               }
+                       }
+               }
+
+               dbgflush();
+               num = sys_select(maxfd+1,&fds,NULL, NULL);
+
+               if (num <= 0)
+               {
+                       continue;
+               }
+
+               if (FD_ISSET(s, &fds))
+               {
+                       FD_CLR(s, &fds);
+                       c = accept(s, (struct sockaddr*)&addr, &in_addrlen);
+                       if (c != -1)
+                       {
+                               sock_add(va, c);
+                       }
+               }
+
+               for (i = 0; i < va->num_socks; i++)
+               {
+                       if (va->socks[i] == NULL)
+                       {
+                               continue;
+                       }
+                       if (FD_ISSET(va->socks[i]->c, &fds))
+                       {
+                               FD_CLR(va->socks[i]->c, &fds);
+                               if (!va->process_cli_sock(va->socks,
+                                                         va->num_socks,
+                                                         va->socks[i]))
+                               {
+                                       sock_redir_free(va, va->socks[i]);
+                                       va->socks[i] = NULL;
+                               }
+                       }
+                       if (va->socks[i] == NULL)
+                       {
+                               continue;
+                       }
+                       if (va->socks[i]->n == NULL)
+                       {
+                               continue;
+                       }
+                       if (FD_ISSET(va->socks[i]->s, &fds))
+                       {
+                               FD_CLR(va->socks[i]->s, &fds);
+                               if (!va->process_srv_sock(va->socks,
+                                                         va->num_socks,
+                                                         va->socks[i]->s))
+                               {
+                                       sock_redir_free(va, va->socks[i]);
+                                       va->socks[i] = NULL;
+                               }
+                       }
+               }
+       }
+}
+
index 457631c307fbd077f1b6448f03a1de1ea9ad722e..5d1aa4db0469079cd36c612c03731e0ce1e84552 100644 (file)
@@ -38,139 +38,19 @@ static char packet[BUFFER_SIZE];
 extern int DEBUGLEVEL;
 
 
-struct sock_redir
-{
-       int c;
-       int s;
-       int mid_offset;
-       struct cli_state *n;
-};
-
-static uint32 num_socks = 0;
-static struct sock_redir **socks = NULL;
 static uint16 mid_offset = 0x0;
 
 /****************************************************************************
 terminate sockent connection
 ****************************************************************************/
-static void sock_redir_free(struct sock_redir *sock)
-{
-       close(sock->c);
-       sock->c = -1;
-       if (sock->n != NULL)
-       {
-               sock->n->fd = sock->s;
-               cli_net_use_del(sock->n->desthost, &sock->n->usr,
-                               False, NULL);
-               sock->n = NULL;
-       }
-       free(sock);
-}
-
-/****************************************************************************
-free a sockent array
-****************************************************************************/
-static void free_sock_array(uint32 num_entries, struct sock_redir **entries)
+static void free_sock(void *sock)
 {
-       void(*fn)(void*) = (void(*)(void*))&sock_redir_free;
-       free_void_array(num_entries, (void**)entries, *fn);
-}
-
-/****************************************************************************
-add a sockent state to the array
-****************************************************************************/
-static struct sock_redir* add_sock_to_array(uint32 *len,
-                               struct sock_redir ***array,
-                               struct sock_redir *sock)
-{
-       int i;
-       for (i = 0; i < num_socks; i++)
-       {
-               if (socks[i] == NULL)
-               {
-                       socks[i] = sock;
-                       return sock;
-               }
-       }
-
-       return (struct sock_redir*)add_item_to_array(len,
-                            (void***)array, (void*)sock);
-                               
-}
-
-/****************************************************************************
-initiate sockent array
-****************************************************************************/
-void init_sock_redir(void)
-{
-       socks = NULL;
-       num_socks = 0;
-}
-
-/****************************************************************************
-terminate sockent array
-****************************************************************************/
-void free_sock_redir(void)
-{
-       free_sock_array(num_socks, socks);
-       init_sock_redir();
-}
-
-/****************************************************************************
-create a new sockent state from user credentials
-****************************************************************************/
-static struct sock_redir *sock_redir_get(int fd)
-{
-       struct sock_redir *sock = (struct sock_redir*)malloc(sizeof(*sock));
-
-       if (sock == NULL)
-       {
-               return NULL;
-       }
-
-       ZERO_STRUCTP(sock);
-
-       sock->c = fd;
-       sock->n = NULL;
-       sock->mid_offset = mid_offset;
-
-       DEBUG(10,("sock_redir_get:\tfd:\t%d\tmidoff:\t%d\n", fd, mid_offset));
-
-       return sock;
-}
-
-/****************************************************************************
-init sock state
-****************************************************************************/
-static void sock_add(int fd)
-{
-       struct sock_redir *sock;
-       sock = sock_redir_get(fd);
        if (sock != NULL)
        {
-               add_sock_to_array(&num_socks, &socks, sock);
-       }
-}
-
-/****************************************************************************
-delete a sockent state
-****************************************************************************/
-static BOOL sock_del(int fd)
-{
-       int i;
-
-       for (i = 0; i < num_socks; i++)
-       {
-               if (socks[i] == NULL) continue;
-               if (socks[i]->c == fd) 
-               {
-                       sock_redir_free(socks[i]);
-                       socks[i] = NULL;
-                       return True;
-               }
+               struct cli_state *n = (struct cli_state*)sock;
+               cli_net_use_del(n->desthost, &n->usr,
+                               False, NULL);
        }
-
-       return False;
 }
 
 static struct cli_state *init_client_connection(int c)
@@ -325,9 +205,10 @@ static void filter_reply(char *buf, int moff)
 
 }
 
-static BOOL process_cli_sock(struct sock_redir *sock)
+static BOOL process_cli_sock(struct sock_redir **socks, uint32 num_socks,
+                               struct sock_redir *sock)
 {
-       struct cli_state *n = sock->n;
+       struct cli_state *n = (struct cli_state*)sock->n;
        if (n == NULL)
        {
                n = init_client_connection(sock->c);
@@ -335,7 +216,9 @@ static BOOL process_cli_sock(struct sock_redir *sock)
                {
                        return False;
                }
-               sock->n = n;
+               sock->n = (void*)n;
+               sock->s_id = mid_offset;
+               sock->s = n->fd;
        }
        else
        {
@@ -345,7 +228,7 @@ static BOOL process_cli_sock(struct sock_redir *sock)
                        return False;
                }
 
-               filter_reply(packet, sock->mid_offset);
+               filter_reply(packet, sock->s_id);
                /* ignore keep-alives */
                if (CVAL(packet, 0) != 0x85)
                {
@@ -371,7 +254,8 @@ static int get_smbmid(char *buf)
        return SVAL(buf,smb_mid);
 }
 
-static BOOL process_srv_sock(int fd)
+static BOOL process_srv_sock(struct sock_redir **socks, uint32 num_socks,
+                               int fd)
 {
        int smbmid;
        int i;
@@ -393,16 +277,18 @@ static BOOL process_srv_sock(int fd)
        for (i = 0; i < num_socks; i++)
        {
                int moff;
+               struct cli_state *n;
                if (socks[i] == NULL || socks[i]->n == NULL)
                {
                        continue;
                }
-               moff = socks[i]->mid_offset;
+               moff = socks[i]->s_id;
+               n = (struct cli_state*)socks[i]->n;
                DEBUG(10,("list:\tfd:\t%d\tmid:\t%d\tmoff:\t%d\n",
                           socks[i]->s,
-                          socks[i]->n->mid,
+                          n->mid,
                           moff));
-               if (smbmid != socks[i]->n->mid + moff)
+               if (smbmid != n->mid + moff)
                {
                        continue;
                }
@@ -417,15 +303,13 @@ static BOOL process_srv_sock(int fd)
        return False;
 }
 
-static void start_agent(void)
+static int get_agent_sock(void *id)
 {
-       int s, c;
+       int s;
        struct sockaddr_un sa;
        fstring path;
        fstring dir;
 
-       CatchChild();
-
        slprintf(dir, sizeof(dir)-1, "/tmp/.smb.%d", getuid());
        mkdir(dir, S_IRUSR|S_IWUSR|S_IXUSR);
 
@@ -470,88 +354,25 @@ static void start_agent(void)
                DEBUG(0,("listen failed\n"));
                remove(path);
        }
+       return s;
+}
 
-       while (1)
+static void start_smb_agent(void)
+{
+       struct vagent_ops va =
        {
-               int i;
-               fd_set fds;
-               int num;
-               struct sockaddr_un addr;
-               int in_addrlen = sizeof(addr);
-               int maxfd = s;
-               
-               FD_ZERO(&fds);
-               FD_SET(s, &fds);
-
-               for (i = 0; i < num_socks; i++)
-               {
-                       if (socks[i] != NULL)
-                       {
-                               int fd = socks[i]->c;
-                               FD_SET(fd, &fds);
-                               maxfd = MAX(maxfd, fd);
-
-                               if (socks[i]->n != NULL)
-                               {
-                                       fd = socks[i]->s;
-                                       FD_SET(fd, &fds);
-                                       maxfd = MAX(fd, maxfd);
-                               }
-                       }
-               }
-
-               dbgflush();
-               num = sys_select(maxfd+1,&fds,NULL, NULL);
-
-               if (num <= 0)
-               {
-                       continue;
-               }
-
-               if (FD_ISSET(s, &fds))
-               {
-                       FD_CLR(s, &fds);
-                       c = accept(s, (struct sockaddr*)&addr, &in_addrlen);
-                       if (c != -1)
-                       {
-                               sock_add(c);
-                       }
-               }
+               free_sock,
+               get_agent_sock,
+               process_cli_sock,
+               process_srv_sock,
+               NULL,
+               NULL,
+               0
+       };
+       
+       CatchChild();
 
-               for (i = 0; i < num_socks; i++)
-               {
-                       if (socks[i] == NULL)
-                       {
-                               continue;
-                       }
-                       if (FD_ISSET(socks[i]->c, &fds))
-                       {
-                               FD_CLR(socks[i]->c, &fds);
-                               if (!process_cli_sock(socks[i]))
-                               {
-                                       sock_redir_free(socks[i]);
-                                       socks[i] = NULL;
-                               }
-                       }
-                       if (socks[i] == NULL)
-                       {
-                               continue;
-                       }
-                       if (socks[i]->n == NULL)
-                       {
-                               continue;
-                       }
-                       if (FD_ISSET(socks[i]->s, &fds))
-                       {
-                               FD_CLR(socks[i]->s, &fds);
-                               if (!process_srv_sock(socks[i]->s))
-                               {
-                                       sock_redir_free(socks[i]);
-                                       socks[i] = NULL;
-                               }
-                       }
-               }
-       }
+       start_agent(&va);
 }
 
 /****************************************************************************
@@ -612,7 +433,7 @@ int main(int argc, char *argv[])
                become_daemon();
        }
 
-       start_agent();
+       start_smb_agent();
 
        return 0;
 }