first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[kai/samba.git] / source / lib / vagent.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2
4    SMB agent/socket plugin
5    Copyright (C) Andrew Tridgell 1999
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "smb.h"
24
25 extern int DEBUGLEVEL;
26
27
28 /****************************************************************************
29 terminate socket connection
30 ****************************************************************************/
31 static void sock_redir_free(struct vagent_ops *va, struct sock_redir *sock)
32 {
33         if (sock->c != -1)
34         {
35                 close(sock->c);
36                 sock->c = -1;
37         }
38         if (sock->n != NULL)
39         {
40                 va->free_sock(sock->n);
41                 sock->n = NULL;
42         }
43         free(sock);
44 }
45
46 /****************************************************************************
47 free a sockent array
48 ****************************************************************************/
49 static void free_sock_array(struct vagent_ops*va)
50 {
51         void(*fn)(void*) = (void(*)(void*))&va->free_sock;
52         free_void_array(va->num_socks, (void**)va->socks, *fn);
53 }
54
55 /****************************************************************************
56 add a sockent state to the array
57 ****************************************************************************/
58 static struct sock_redir* add_sock_to_array(uint32 *len,
59                                 struct sock_redir ***array,
60                                 struct sock_redir *sock)
61 {
62         int i;
63         for (i = 0; i < (*len); i++)
64         {
65                 if ((*array)[i] == NULL)
66                 {
67                         (*array)[i] = sock;
68                         return sock;
69                 }
70         }
71
72         return (struct sock_redir*)add_item_to_array(len,
73                              (void***)array, (void*)sock);
74                                 
75 }
76
77 /****************************************************************************
78 initiate sockent array
79 ****************************************************************************/
80 void init_sock_redir(struct vagent_ops*va)
81 {
82         va->socks = NULL;
83         va->num_socks = 0;
84 }
85
86 /****************************************************************************
87 terminate sockent array
88 ****************************************************************************/
89 void free_sock_redir(struct vagent_ops*va)
90 {
91         free_sock_array(va);
92         init_sock_redir(va);
93 }
94
95 /****************************************************************************
96 create a new sockent state from user credentials
97 ****************************************************************************/
98 static struct sock_redir *sock_redir_get(struct vagent_ops *va, int fd)
99 {
100         struct sock_redir *sock = (struct sock_redir*)malloc(sizeof(*sock));
101
102         if (sock == NULL)
103         {
104                 return NULL;
105         }
106
107         ZERO_STRUCTP(sock);
108
109         sock->c = fd;
110         sock->n = NULL;
111
112         DEBUG(10,("sock_redir_get:\tfd:\t%d\n", fd));
113
114         return sock;
115 }
116 /****************************************************************************
117 init sock state
118 ****************************************************************************/
119 static void sock_add(struct vagent_ops *va, int fd)
120 {
121         struct sock_redir *sock;
122         sock = sock_redir_get(va, fd);
123         if (sock != NULL)
124         {
125                 add_sock_to_array(&va->num_socks, &va->socks, sock);
126         }
127 }
128
129 /****************************************************************************
130 delete a sockent state
131 ****************************************************************************/
132 static BOOL sock_del(struct vagent_ops *va, int fd)
133 {
134         int i;
135
136         for (i = 0; i < va->num_socks; i++)
137         {
138                 if (va->socks[i] == NULL) continue;
139                 if (va->socks[i]->c == fd) 
140                 {
141                         sock_redir_free(va, va->socks[i]);
142                         va->socks[i] = NULL;
143                         return True;
144                 }
145         }
146
147         return False;
148 }
149
150 void start_agent(struct vagent_ops *va)
151 {
152         int s, c;
153
154         s = va->get_agent_sock(va->id);
155
156         while (1)
157         {
158                 int i;
159                 fd_set fds;
160                 int num;
161                 struct sockaddr_un addr;
162                 int in_addrlen = sizeof(addr);
163                 int maxfd = s;
164                 
165                 FD_ZERO(&fds);
166                 FD_SET(s, &fds);
167
168                 for (i = 0; i < va->num_socks; i++)
169                 {
170                         if (va->socks[i] != NULL)
171                         {
172                                 int fd = va->socks[i]->c;
173                                 FD_SET(fd, &fds);
174                                 maxfd = MAX(maxfd, fd);
175
176                                 if (va->socks[i]->n != NULL)
177                                 {
178                                         fd = va->socks[i]->s;
179                                         FD_SET(fd, &fds);
180                                         maxfd = MAX(fd, maxfd);
181                                 }
182                         }
183                 }
184
185                 dbgflush();
186                 num = sys_select(maxfd+1,&fds,NULL, NULL);
187
188                 if (num <= 0)
189                 {
190                         continue;
191                 }
192
193                 if (FD_ISSET(s, &fds))
194                 {
195                         FD_CLR(s, &fds);
196                         c = accept(s, (struct sockaddr*)&addr, &in_addrlen);
197                         if (c != -1)
198                         {
199                                 sock_add(va, c);
200                         }
201                 }
202
203                 for (i = 0; i < va->num_socks; i++)
204                 {
205                         if (va->socks[i] == NULL)
206                         {
207                                 continue;
208                         }
209                         if (FD_ISSET(va->socks[i]->c, &fds))
210                         {
211                                 FD_CLR(va->socks[i]->c, &fds);
212                                 if (!va->process_cli_sock(va->socks,
213                                                           va->num_socks,
214                                                           va->socks[i]))
215                                 {
216                                         sock_redir_free(va, va->socks[i]);
217                                         va->socks[i] = NULL;
218                                 }
219                         }
220                         if (va->socks[i] == NULL)
221                         {
222                                 continue;
223                         }
224                         if (va->socks[i]->n == NULL)
225                         {
226                                 continue;
227                         }
228                         if (FD_ISSET(va->socks[i]->s, &fds))
229                         {
230                                 FD_CLR(va->socks[i]->s, &fds);
231                                 if (!va->process_srv_sock(va->socks,
232                                                           va->num_socks,
233                                                           va->socks[i]->s))
234                                 {
235                                         sock_redir_free(va, va->socks[i]);
236                                         va->socks[i] = NULL;
237                                 }
238                         }
239                 }
240         }
241 }
242