patch-2.3.14 linux/net/khttpd/rfc.c

Next file: linux/net/khttpd/rfc_time.c
Previous file: linux/net/khttpd/prototypes.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.13/linux/net/khttpd/rfc.c linux/net/khttpd/rfc.c
@@ -0,0 +1,375 @@
+/*
+
+kHTTPd -- the next generation
+
+RFC related functions (headers and stuff)
+
+*/
+
+/****************************************************************
+ *	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, 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 <linux/kernel.h>
+
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/net.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/unistd.h>
+#include <linux/file.h>
+#include <linux/smp_lock.h>
+
+#include <net/ip.h>
+#include <net/sock.h>
+
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/msr.h>
+
+
+#include "prototypes.h"
+#include "structure.h"
+#include "sysctl.h"
+
+
+#define KHTTPD_NUMMIMETYPES 	40
+
+static atomic_t	MimeCount;
+
+struct MimeType
+{
+	__u32 	identifier;
+	char	type[64-sizeof(__u32)-sizeof(__kernel_size_t)];  
+	__kernel_size_t	len;
+};
+
+static struct MimeType	MimeTypes[KHTTPD_NUMMIMETYPES];
+
+
+void AddMimeType(const char *Ident,const char *Type)
+{	
+	__u32	*I;
+	
+	EnterFunction("AddMimeType");
+	
+	if (strlen(Ident)!=4) 
+   	{	
+   		(void)printk(KERN_ERR "httpd: Only 4-byte mime-identifiers are accepted\n");
+   		return;
+   	}
+
+	if (strlen(Type)>(64-sizeof(__u32)-sizeof(__kernel_size_t) ) )  
+   	{	
+   		(void)printk(KERN_ERR "httpd: Mime-string too long.\n");
+   		return;
+   	}
+   	
+   	I=(__u32*)Ident;
+   	
+   	/* FIXME: Need to lock-down all access to the mime-structure here */
+   	/*        For now, just don't add mime-types after initialisation */
+   	
+   	
+   	MimeTypes[atomic_read(&MimeCount)].identifier=*I;
+   	strcpy(MimeTypes[atomic_read(&MimeCount)].type,Type);
+   	MimeTypes[atomic_read(&MimeCount)].len = strlen(Type);
+   	
+   	atomic_inc(&MimeCount);
+   	LeaveFunction("AddMimeType");
+}
+
+
+char *ResolveMimeType(const char *File,__kernel_size_t *Len)
+/*
+
+	The returned string is for READ ONLY, ownership of the memory is NOT
+	transfered.
+
+*/
+{	
+	__u32	*I;
+	int pos,lc,filelen;
+	
+	EnterFunction("ResolveMimeType");
+	
+	*Len = 0;
+	
+	if (File==NULL)
+		return NULL;
+	
+	filelen = (int)strlen(File);
+	
+	if (filelen<4) 
+   	{	
+   		return NULL;
+   	}
+   	
+   	/* The Merced-people are NOT going to like this! So this has to be fixed
+   	   in a later stage. */
+
+	pos = filelen-4;
+   	I=(__u32*)(File+pos);
+   	
+   	lc=0;
+   	
+   	while (lc<atomic_read(&MimeCount))
+ 	{
+   		if (MimeTypes[lc].identifier == *I)
+   		{
+   			*Len = MimeTypes[lc].len;
+   			LeaveFunction("ResolveMimeType - success");
+   	  		return MimeTypes[lc].type;
+   	  	}
+   	  	lc++;
+   	} 	
+   	
+	if (sysctl_khttpd_sloppymime)
+	{
+		*Len = MimeTypes[0].len;  
+		LeaveFunction("ResolveMimeType - unknown");
+	   	return MimeTypes[0].type;
+	}
+	else
+	{
+		LeaveFunction("ResolveMimeType - failure");
+	   	return NULL;
+	}
+}
+
+
+static char HeaderPart1[] = "HTTP/1.0 200 OK\r\nServer: kHTTPd/0.1.6\r\nDate: ";
+#ifdef BENCHMARK
+static char HeaderPart1b[] ="HTTP/1.0 200 OK";
+#endif
+static char HeaderPart3[] = "\r\nContent-type: ";
+static char HeaderPart5[] = "\r\nLast-modified: ";
+static char HeaderPart7[] = "\r\nContent-length: ";
+static char HeaderPart9[] = "\r\n\r\n";
+
+#ifdef BENCHMARK
+/* In BENCHMARK-mode, just send the bare essentials */
+void SendHTTPHeader(struct http_request *Request)
+{
+	struct msghdr	msg;
+	mm_segment_t	oldfs;
+	struct iovec	iov[9];
+	int 		len,len2;
+	
+	
+	EnterFunction("SendHTTPHeader");
+		
+	msg.msg_name     = 0;
+	msg.msg_namelen  = 0;
+	msg.msg_iov	 = &iov[0];
+	msg.msg_iovlen   = 6;
+	msg.msg_control  = NULL;
+	msg.msg_controllen = 0;
+	msg.msg_flags    = 0;  /* Synchronous for now */
+	
+	iov[0].iov_base = HeaderPart1b;
+	iov[0].iov_len  = 15;
+	iov[1].iov_base = HeaderPart3;
+	iov[1].iov_len  = 16;
+	iov[2].iov_base = Request->MimeType;
+	iov[2].iov_len  = Request->MimeLength;
+	
+	iov[3].iov_base = HeaderPart7;
+	iov[3].iov_len  = 18;
+	
+	
+	sprintf(Request->LengthS,"%i",Request->FileLength);
+	iov[4].iov_base = Request->LengthS;
+	iov[4].iov_len  = strlen(Request->LengthS);
+	iov[5].iov_base = HeaderPart9;
+	iov[5].iov_len  = 4;
+	
+	len2=15+16+18+iov[2].iov_len+iov[4].iov_len+4;
+	
+	
+	len = 0;
+	
+
+	oldfs = get_fs(); set_fs(KERNEL_DS);
+	len = sock_sendmsg(Request->sock,&msg,len2);
+	set_fs(oldfs);
+
+	
+	return;	
+}
+#else
+void SendHTTPHeader(struct http_request *Request)
+{
+	struct msghdr	msg;
+	mm_segment_t	oldfs;
+	struct iovec	iov[9];
+	int 		len,len2;
+	__kernel_size_t	slen;
+	
+	EnterFunction("SendHTTPHeader");
+	
+	msg.msg_name     = 0;
+	msg.msg_namelen  = 0;
+	msg.msg_iov	 = &(iov[0]);
+	msg.msg_iovlen   = 9;
+	msg.msg_control  = NULL;
+	msg.msg_controllen = 0;
+	msg.msg_flags    = 0;  /* Synchronous for now */
+	
+	iov[0].iov_base = HeaderPart1;
+	iov[0].iov_len  = 45;
+	iov[1].iov_base = CurrentTime;
+	iov[1].iov_len  = 29;
+	iov[2].iov_base = HeaderPart3;
+	iov[2].iov_len  = 16;
+	
+	iov[3].iov_base = Request->MimeType;
+	iov[3].iov_len  = Request->MimeLength;
+	
+	iov[4].iov_base = HeaderPart5;
+	iov[4].iov_len  = 17;
+	iov[5].iov_base = &(Request->TimeS[0]);
+	iov[5].iov_len  = 29;
+	iov[6].iov_base = HeaderPart7;
+	iov[6].iov_len  = 18;
+	iov[7].iov_base = &(Request->LengthS[0]);
+	slen = strlen(Request->LengthS); 
+	iov[7].iov_len  = slen;
+	iov[8].iov_base = HeaderPart9;
+	iov[8].iov_len  = 4;
+	
+	len2=45+2*29+16+17+18+slen+4+iov[3].iov_len;
+	
+	len = 0;
+
+	oldfs = get_fs(); set_fs(KERNEL_DS);
+	len = sock_sendmsg(Request->sock,&msg,len2);
+	set_fs(oldfs);
+	LeaveFunction("SendHTTPHeader");
+	
+
+	return;	
+}
+#endif
+
+
+
+/* 
+
+Parse a HTTP-header. Be careful for buffer-overflows here, this is the most important
+place for this, since the remote-user controls the data.
+
+*/
+void ParseHeader(char *Buffer,const int length, struct http_request *Head)
+{
+	char *Endval,*EOL,*tmp;
+	
+	EnterFunction("ParseHeader");
+	Endval = Buffer + length;
+	
+	/* We want to parse only the first header if multiple headers are present */
+	tmp = strstr(Buffer,"\r\n\r\n"); 
+	if (tmp!=NULL)
+	    Endval = tmp;
+	
+	
+	while (Buffer<Endval)
+	{
+		if (isspace(Buffer[0]))
+		{
+			Buffer++;
+			continue;
+		}
+			
+		
+		EOL=strchr(Buffer,'\n');
+		
+		if (EOL==NULL) EOL=Endval;
+		
+		if (EOL-Buffer<4) 
+		{
+			Buffer++;
+			continue;
+		}
+		
+		if (strncmp("GET ",Buffer,4)==0)
+		{
+			int PrefixLen;
+			Buffer+=4;
+			
+			tmp=strchr(Buffer,' ');
+			if (tmp==0) 
+			{
+				tmp=EOL-1;
+				Head->HTTPVER = 9;
+			} else
+				Head->HTTPVER = 10;
+			
+			if (tmp>Endval) continue;
+			
+			strcpy(Head->FileName,sysctl_khttpd_docroot);
+			PrefixLen = strlen(sysctl_khttpd_docroot);
+			Head->FileNameLength = min(255,tmp-Buffer+PrefixLen);		
+			
+			strncat(Head->FileName,Buffer,min(255-PrefixLen,tmp-Buffer));
+					
+			Buffer=EOL+1;	
+#ifdef BENCHMARK
+			break;
+#endif						
+			continue;
+		}
+#ifndef BENCHMARK		
+		if (strncmp("If-Modified-Since: ",Buffer,19)==0)
+		{
+			Buffer+=19;
+			
+			strncpy(Head->IMS,Buffer,min(127,EOL-Buffer-1));
+					
+			Buffer=EOL+1;	
+			continue;
+		}
+
+		if (strncmp("User-Agent: ",Buffer,12)==0)
+		{
+			Buffer+=12;
+			
+			strncpy(Head->Agent,Buffer,min(127,EOL-Buffer-1));
+					
+			Buffer=EOL+1;	
+			continue;
+		}
+		
+
+		if (strncmp("Host: ",Buffer,6)==0)
+		{
+			Buffer+=6;
+			
+			strncpy(Head->Host,Buffer,min(127,EOL-Buffer-1));
+					
+			Buffer=EOL+1;	
+			continue;
+		}
+#endif		
+		Buffer = EOL+1;  /* Skip line */
+	}
+	LeaveFunction("ParseHeader");
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)