import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / net / khttpd / userspace.c
1 /*
2
3 kHTTPd -- the next generation
4
5 Pass connections to userspace-daemons
6
7 */
8 /****************************************************************
9  *      This program is free software; you can redistribute it and/or modify
10  *      it under the terms of the GNU General Public License as published by
11  *      the Free Software Foundation; either version 2, or (at your option)
12  *      any later version.
13  *
14  *      This program is distributed in the hope that it will be useful,
15  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *      GNU General Public License for more details.
18  *
19  *      You should have received a copy of the GNU General Public License
20  *      along with this program; if not, write to the Free Software
21  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  ****************************************************************/
24
25 /*
26
27 Purpose:
28
29 Userspace() hands all requests in the queue to the userspace-daemon, if
30 such beast exists.
31
32 Return value:
33         The number of requests that changed status
34 */
35 #include <linux/kernel.h>
36
37 #include <linux/errno.h>
38 #include <linux/slab.h>
39 #include <linux/net.h>
40 #include <linux/sched.h>
41 #include <linux/skbuff.h>
42 #include <linux/smp_lock.h>
43 #include <linux/un.h>
44 #include <linux/unistd.h>
45 #include <linux/wait.h>
46
47 #include <net/ip.h>
48 #include <net/sock.h>
49 #include <net/tcp.h>
50
51 #include <asm/atomic.h>
52 #include <asm/semaphore.h>
53 #include <asm/processor.h>
54 #include <asm/uaccess.h>
55
56 #include <linux/file.h>
57
58
59 #include "structure.h"
60 #include "prototypes.h"
61 #include "sysctl.h"
62
63 /* prototypes of local, static functions */
64 static int AddSocketToAcceptQueue(struct socket *sock,const int Port);
65
66
67 int Userspace(const int CPUNR)
68 {
69         struct http_request *CurrentRequest,**Prev,*Next;
70         
71         EnterFunction("Userspace");
72
73         
74
75         
76         CurrentRequest = threadinfo[CPUNR].UserspaceQueue;
77         Prev = &(threadinfo[CPUNR].UserspaceQueue);
78         
79         while (CurrentRequest!=NULL)
80         {
81
82                 /* Clean-up the waitqueue of the socket.. Bad things happen if
83                    this is forgotten. */
84                 if (CurrentRequest->sock!=NULL)
85                 {
86                         if ((CurrentRequest->sock!=NULL)&&(CurrentRequest->sock->sk!=NULL))
87                         {
88                                 remove_wait_queue(CurrentRequest->sock->sk->sleep,&(CurrentRequest->sleep));
89                         }
90                 } 
91                 
92
93                 if  (AddSocketToAcceptQueue(CurrentRequest->sock,sysctl_khttpd_clientport)>=0)
94                 {
95                         
96                         (*Prev) = CurrentRequest->Next;
97                         Next = CurrentRequest->Next;
98                         
99                         
100                         sock_release(CurrentRequest->sock);
101                         CurrentRequest->sock = NULL;     /* We no longer own it */
102                         
103                         CleanUpRequest(CurrentRequest); 
104                                 
105                         CurrentRequest = Next;
106                         continue;
107                 
108                 }
109                 else /* No userspace-daemon present, or other problems with it */
110                 {
111                         (*Prev) = CurrentRequest->Next;
112                         Next = CurrentRequest->Next;
113                         
114                         Send403(CurrentRequest->sock); /* Sorry, no go... */
115                         
116                         CleanUpRequest(CurrentRequest); 
117                                 
118                         CurrentRequest = Next;
119                         continue;
120                 
121                 }
122
123                 
124                 Prev = &(CurrentRequest->Next); 
125                 CurrentRequest = CurrentRequest->Next;
126         }
127         
128         LeaveFunction("Userspace");
129         return 0;
130 }
131
132 void StopUserspace(const int CPUNR)
133 {
134         struct http_request *CurrentRequest,*Next;
135         
136         EnterFunction("StopUserspace");
137         CurrentRequest = threadinfo[CPUNR].UserspaceQueue;
138
139         while (CurrentRequest!=NULL)
140         {
141                 Next= CurrentRequest->Next;
142                 CleanUpRequest(CurrentRequest);
143                 CurrentRequest=Next;            
144         }
145         threadinfo[CPUNR].UserspaceQueue = NULL;
146         
147         LeaveFunction("StopUserspace");
148 }
149
150
151 /* 
152    "FindUserspace" returns the struct sock of the userspace-daemon, so that we can
153    "drop" our request in the accept-queue 
154 */
155
156 static struct sock *FindUserspace(const unsigned short Port)
157 {
158         struct sock *sk;
159
160         EnterFunction("FindUserspace");
161
162         local_bh_disable();
163         sk = tcp_v4_lookup_listener(INADDR_ANY,Port,0);
164         local_bh_enable();
165         return sk;
166 }
167
168 static void dummy_destructor(struct open_request *req)
169 {
170 }
171
172 static struct or_calltable Dummy = 
173 {
174         0,
175         NULL,
176         NULL,
177         &dummy_destructor,
178         NULL
179 };
180
181 static int AddSocketToAcceptQueue(struct socket *sock,const int Port)
182 {
183         struct open_request *req;
184         struct sock *sk, *nsk;
185         
186         EnterFunction("AddSocketToAcceptQueue");
187
188         
189         sk = FindUserspace((unsigned short)Port);       
190         
191         if (sk==NULL)   /* No userspace-daemon found */
192         {
193                 return -1;
194         }
195         
196         lock_sock(sk);
197
198         if (sk->state != TCP_LISTEN || tcp_acceptq_is_full(sk))
199         {
200                 release_sock(sk);
201                 sock_put(sk);
202                 return -1;
203         }
204
205         req = tcp_openreq_alloc();
206         
207         if (req==NULL)
208         {       
209                 release_sock(sk);
210                 sock_put(sk);
211                 return -1;
212         }
213         
214         nsk = sock->sk;
215         sock->sk = NULL;
216         sock->state = SS_UNCONNECTED;
217
218         req->class      = &Dummy;
219         write_lock_bh(&nsk->callback_lock);
220         nsk->socket = NULL;
221         nsk->sleep  = NULL;
222         write_unlock_bh(&nsk->callback_lock);
223
224         tcp_acceptq_queue(sk, req, nsk);        
225
226         sk->data_ready(sk, 0);
227
228         release_sock(sk);
229         sock_put(sk);
230
231         LeaveFunction("AddSocketToAcceptQueue");
232                 
233         return +1;      
234         
235         
236         
237 }
238
239 void InitUserspace(const int CPUNR)
240 {
241 }
242
243