mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
cool! created higher-order function table for agent redirection.
This commit is contained in:
parent
2c778313b8
commit
7bb2e55d0d
@ -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 \
|
||||
|
@ -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);
|
||||
|
@ -550,6 +550,9 @@ typedef struct
|
||||
|
||||
#include "vfs.h"
|
||||
|
||||
|
||||
#include "vagent.h"
|
||||
|
||||
typedef struct connection_struct
|
||||
{
|
||||
struct connection_struct *next, *prev;
|
||||
|
51
source/include/vagent.h
Normal file
51
source/include/vagent.h
Normal file
@ -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 */
|
242
source/lib/vagent.c
Normal file
242
source/lib/vagent.c
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,141 +38,21 @@ 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)
|
||||
static void free_sock(void *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)
|
||||
{
|
||||
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);
|
||||
struct cli_state *n = (struct cli_state*)sock;
|
||||
cli_net_use_del(n->desthost, &n->usr,
|
||||
False, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
static struct cli_state *init_client_connection(int c)
|
||||
{
|
||||
pstring buf;
|
||||
@ -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);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user