1/* 2 3kHTTPd -- the next generation 4 5General 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 56Readrest reads and discards all pending input on a socket. This is required 57before closing the socket. 58 59*/ 60static 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 104CleanUpRequest takes care of shutting down the connection, closing the file-pointer 105and releasing the memory of the request-structure. Do not try to access it afterwards! 106 107*/ 108void 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 138SendBuffer and Sendbuffer_async send "Length" bytes from "Buffer" to the "sock"et. 139The _async-version is non-blocking. 140 141A positive return-value indicates the number of bytes sent, a negative value indicates 142an error-condition. 143 144*/ 145int 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 174int 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 212HTTP header shortcuts. Hardcoded since these might be called in a low-memory 213situation, and they don't change anyhow. 214 215*/ 216 217static char NoPerm[] = "HTTP/1.0 403 Forbidden\r\nServer: kHTTPd 0.1.6\r\n\r\n"; 218static char TryLater[] = "HTTP/1.0 503 Service Unavailable\r\nServer: kHTTPd 0.1.6\r\nContent-Length: 15\r\n\r\nTry again later"; 219static char NotModified[] = "HTTP/1.0 304 Not Modified\r\nServer: kHTTPd 0.1.6\r\n\r\n"; 220 221 222void Send403(struct socket *sock) 223{ 224 EnterFunction("Send403"); 225 (void)SendBuffer(sock,NoPerm,strlen(NoPerm)); 226 LeaveFunction("Send403"); 227} 228 229void Send304(struct socket *sock) 230{ 231 EnterFunction("Send304"); 232 (void)SendBuffer(sock,NotModified,strlen(NotModified)); 233 LeaveFunction("Send304"); 234} 235 236void Send50x(struct socket *sock) 237{ 238 EnterFunction("Send50x"); 239 (void)SendBuffer(sock,TryLater,strlen(TryLater)); 240 LeaveFunction("Send50x"); 241} 242 243