rfc.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
- /*
- 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/slab.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 "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 acceptedn");
- 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;
- strncpy(MimeTypes[atomic_read(&MimeCount)].type,Type,(64-sizeof(__u32)-sizeof(__kernel_size_t)));
- 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
- transferred.
- */
- {
- __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 OKrnServer: kHTTPd/0.1.6rnDate: ";
- #ifdef BENCHMARK
- static char HeaderPart1b[] ="HTTP/1.0 200 OK";
- #endif
- static char HeaderPart3[] = "rnContent-type: ";
- static char HeaderPart5[] = "rnLast-modified: ";
- static char HeaderPart7[] = "rnContent-length: ";
- static char HeaderPart9[] = "rnrn";
- #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,"rnrn");
- 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;
-
- strncpy(Head->FileName,sysctl_khttpd_docroot,sizeof(Head->FileName));
- PrefixLen = strlen(sysctl_khttpd_docroot);
- Head->FileNameLength = min_t(unsigned int, 255, tmp - Buffer + PrefixLen);
-
- strncat(Head->FileName,Buffer,min_t(unsigned int, 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_t(unsigned int, 127,EOL-Buffer-1));
-
- Buffer=EOL+1;
- continue;
- }
- if (strncmp("User-Agent: ",Buffer,12)==0)
- {
- Buffer+=12;
-
- strncpy(Head->Agent,Buffer,min_t(unsigned int, 127,EOL-Buffer-1));
-
- Buffer=EOL+1;
- continue;
- }
-
- if (strncmp("Host: ",Buffer,6)==0)
- {
- Buffer+=6;
-
- strncpy(Head->Host,Buffer,min_t(unsigned int, 127,EOL-Buffer-1));
-
- Buffer=EOL+1;
- continue;
- }
- #endif
- Buffer = EOL+1; /* Skip line */
- }
- LeaveFunction("ParseHeader");
- }