1 /*
2
3 kHTTPd -- the next generation
4
5 General functions
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 #include <linux/kernel.h>
26
27 #include <linux/ctype.h>
28 #include <linux/errno.h>
29 #include <linux/slab.h>
30 #include <linux/net.h>
31 #include <linux/sched.h>
32 #include <linux/skbuff.h>
33 #include <linux/unistd.h>
34 #include <linux/file.h>
35 #include <linux/smp_lock.h>
36
37 #include <net/ip.h>
38 #include <net/sock.h>
39
40 #include <asm/atomic.h>
41 #include <asm/errno.h>
42 #include <asm/semaphore.h>
43 #include <asm/processor.h>
44 #include <asm/uaccess.h>
45
46 #include "structure.h"
47 #include "prototypes.h"
48
49 #ifndef ECONNRESET
50 #define ECONNRESET 102
51 #endif
52
53
54 /*
55
56 Readrest reads and discards all pending input on a socket. This is required
57 before closing the socket.
58
59 */
ReadRest(struct socket * sock)60 static void ReadRest(struct socket *sock)
61 {
62 struct msghdr msg;
63 struct iovec iov;
64 int len;
65
66 mm_segment_t oldfs;
67
68
69 EnterFunction("ReadRest");
70
71
72 if (sock->sk==NULL)
73 return;
74
75 len = 1;
76
77 while (len>0)
78 {
79 static char Buffer[1024]; /* Never read, so doesn't need to
80 be SMP safe */
81
82 msg.msg_name = 0;
83 msg.msg_namelen = 0;
84 msg.msg_iov = &iov;
85 msg.msg_iovlen = 1;
86 msg.msg_control = NULL;
87 msg.msg_controllen = 0;
88 msg.msg_flags = MSG_DONTWAIT;
89
90 msg.msg_iov->iov_base = &Buffer[0];
91 msg.msg_iov->iov_len = (__kernel_size_t)1024;
92
93 len = 0;
94 oldfs = get_fs(); set_fs(KERNEL_DS);
95 len = sock_recvmsg(sock,&msg,1024,MSG_DONTWAIT);
96 set_fs(oldfs);
97 }
98 LeaveFunction("ReadRest");
99 }
100
101
102 /*
103
104 CleanUpRequest takes care of shutting down the connection, closing the file-pointer
105 and releasing the memory of the request-structure. Do not try to access it afterwards!
106
107 */
CleanUpRequest(struct http_request * Req)108 void CleanUpRequest(struct http_request *Req)
109 {
110 EnterFunction("CleanUpRequest");
111
112 /* Close the socket ....*/
113 if ((Req->sock!=NULL)&&(Req->sock->sk!=NULL))
114 {
115 ReadRest(Req->sock);
116 remove_wait_queue(Req->sock->sk->sleep,&(Req->sleep));
117 sock_release(Req->sock);
118 }
119
120 /* ... and the file-pointer ... */
121 if (Req->filp!=NULL)
122 {
123 fput(Req->filp);
124 Req->filp = NULL;
125 }
126
127
128 /* ... and release the memory for the structure. */
129 kfree(Req);
130
131 atomic_dec(&ConnectCount);
132 LeaveFunction("CleanUpRequest");
133 }
134
135
136 /*
137
138 SendBuffer and Sendbuffer_async send "Length" bytes from "Buffer" to the "sock"et.
139 The _async-version is non-blocking.
140
141 A positive return-value indicates the number of bytes sent, a negative value indicates
142 an error-condition.
143
144 */
SendBuffer(struct socket * sock,const char * Buffer,const size_t Length)145 int SendBuffer(struct socket *sock, const char *Buffer,const size_t Length)
146 {
147 struct msghdr msg;
148 mm_segment_t oldfs;
149 struct iovec iov;
150 int len;
151
152 EnterFunction("SendBuffer");
153
154 msg.msg_name = 0;
155 msg.msg_namelen = 0;
156 msg.msg_iov = &iov;
157 msg.msg_iovlen = 1;
158 msg.msg_control = NULL;
159 msg.msg_controllen = 0;
160 msg.msg_flags = MSG_NOSIGNAL;
161 msg.msg_iov->iov_len = (__kernel_size_t)Length;
162 msg.msg_iov->iov_base = (char*) Buffer;
163
164
165 len = 0;
166
167 oldfs = get_fs(); set_fs(KERNEL_DS);
168 len = sock_sendmsg(sock,&msg,(size_t)(Length-len));
169 set_fs(oldfs);
170 LeaveFunction("SendBuffer");
171 return len;
172 }
173
SendBuffer_async(struct socket * sock,const char * Buffer,const size_t Length)174 int SendBuffer_async(struct socket *sock, const char *Buffer,const size_t Length)
175 {
176 struct msghdr msg;
177 mm_segment_t oldfs;
178 struct iovec iov;
179 int len;
180
181 EnterFunction("SendBuffer_async");
182 msg.msg_name = 0;
183 msg.msg_namelen = 0;
184 msg.msg_iov = &iov;
185 msg.msg_iovlen = 1;
186 msg.msg_control = NULL;
187 msg.msg_controllen = 0;
188 msg.msg_flags = MSG_DONTWAIT|MSG_NOSIGNAL;
189 msg.msg_iov->iov_base = (char*) Buffer;
190 msg.msg_iov->iov_len = (__kernel_size_t)Length;
191
192
193 if (sock->sk)
194 {
195 oldfs = get_fs(); set_fs(KERNEL_DS);
196 len = sock_sendmsg(sock,&msg,(size_t)(Length));
197 set_fs(oldfs);
198 } else
199 {
200 return -ECONNRESET;
201 }
202
203 LeaveFunction("SendBuffer_async");
204 return len;
205 }
206
207
208
209
210 /*
211
212 HTTP header shortcuts. Hardcoded since these might be called in a low-memory
213 situation, and they don't change anyhow.
214
215 */
216
217 static char NoPerm[] = "HTTP/1.0 403 Forbidden\r\nServer: kHTTPd 0.1.6\r\n\r\n";
218 static char TryLater[] = "HTTP/1.0 503 Service Unavailable\r\nServer: kHTTPd 0.1.6\r\nContent-Length: 15\r\n\r\nTry again later";
219 static char NotModified[] = "HTTP/1.0 304 Not Modified\r\nServer: kHTTPd 0.1.6\r\n\r\n";
220
221
Send403(struct socket * sock)222 void Send403(struct socket *sock)
223 {
224 EnterFunction("Send403");
225 (void)SendBuffer(sock,NoPerm,strlen(NoPerm));
226 LeaveFunction("Send403");
227 }
228
Send304(struct socket * sock)229 void Send304(struct socket *sock)
230 {
231 EnterFunction("Send304");
232 (void)SendBuffer(sock,NotModified,strlen(NotModified));
233 LeaveFunction("Send304");
234 }
235
Send50x(struct socket * sock)236 void Send50x(struct socket *sock)
237 {
238 EnterFunction("Send50x");
239 (void)SendBuffer(sock,TryLater,strlen(TryLater));
240 LeaveFunction("Send50x");
241 }
242
243