/* 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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; 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 (lcMimeType; 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 (BufferHTTPVER = 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(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"); }