rfc.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2. kHTTPd -- the next generation
  3. RFC related functions (headers and stuff)
  4. */
  5. /****************************************************************
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  ****************************************************************/
  21. #include <linux/kernel.h>
  22. #include <linux/ctype.h>
  23. #include <linux/errno.h>
  24. #include <linux/slab.h>
  25. #include <linux/net.h>
  26. #include <linux/sched.h>
  27. #include <linux/skbuff.h>
  28. #include <linux/unistd.h>
  29. #include <linux/file.h>
  30. #include <linux/smp_lock.h>
  31. #include <net/ip.h>
  32. #include <net/sock.h>
  33. #include <asm/atomic.h>
  34. #include <asm/semaphore.h>
  35. #include <asm/processor.h>
  36. #include <asm/uaccess.h>
  37. #include "prototypes.h"
  38. #include "structure.h"
  39. #include "sysctl.h"
  40. #define KHTTPD_NUMMIMETYPES  40
  41. static atomic_t MimeCount;
  42. struct MimeType
  43. {
  44. __u32  identifier;
  45. char type[64-sizeof(__u32)-sizeof(__kernel_size_t)];  
  46. __kernel_size_t len;
  47. };
  48. static struct MimeType MimeTypes[KHTTPD_NUMMIMETYPES];
  49. void AddMimeType(const char *Ident,const char *Type)
  50. {
  51. __u32 *I;
  52. EnterFunction("AddMimeType");
  53. if (strlen(Ident)!=4) 
  54.     {
  55.     (void)printk(KERN_ERR "httpd: Only 4-byte mime-identifiers are acceptedn");
  56.     return;
  57.     }
  58. if (strlen(Type)>(64-sizeof(__u32)-sizeof(__kernel_size_t) ) )  
  59.     {
  60.     (void)printk(KERN_ERR "httpd: Mime-string too long.n");
  61.     return;
  62.     }
  63.    
  64.     I=(__u32*)Ident;
  65.    
  66.     /* FIXME: Need to lock-down all access to the mime-structure here */
  67.     /*        For now, just don't add mime-types after initialisation */
  68.    
  69.    
  70.     MimeTypes[atomic_read(&MimeCount)].identifier=*I;
  71.     strncpy(MimeTypes[atomic_read(&MimeCount)].type,Type,(64-sizeof(__u32)-sizeof(__kernel_size_t)));
  72.     MimeTypes[atomic_read(&MimeCount)].len = strlen(Type);
  73.    
  74.     atomic_inc(&MimeCount);
  75.     LeaveFunction("AddMimeType");
  76. }
  77. char *ResolveMimeType(const char *File,__kernel_size_t *Len)
  78. /*
  79. The returned string is for READ ONLY, ownership of the memory is NOT
  80. transferred.
  81. */
  82. {
  83. __u32 *I;
  84. int pos,lc,filelen;
  85. EnterFunction("ResolveMimeType");
  86. *Len = 0;
  87. if (File==NULL)
  88. return NULL;
  89. filelen = (int)strlen(File);
  90. if (filelen<4) 
  91.     {
  92.     return NULL;
  93.     }
  94.    
  95.     /* The Merced-people are NOT going to like this! So this has to be fixed
  96.        in a later stage. */
  97. pos = filelen-4;
  98.     I=(__u32*)(File+pos);
  99.    
  100.     lc=0;
  101.    
  102.     while (lc<atomic_read(&MimeCount))
  103.   {
  104.     if (MimeTypes[lc].identifier == *I)
  105.     {
  106.     *Len = MimeTypes[lc].len;
  107.     LeaveFunction("ResolveMimeType - success");
  108.        return MimeTypes[lc].type;
  109.        }
  110.        lc++;
  111.     } 
  112.    
  113. if (sysctl_khttpd_sloppymime)
  114. {
  115. *Len = MimeTypes[0].len;  
  116. LeaveFunction("ResolveMimeType - unknown");
  117.     return MimeTypes[0].type;
  118. }
  119. else
  120. {
  121. LeaveFunction("ResolveMimeType - failure");
  122.     return NULL;
  123. }
  124. }
  125. static char HeaderPart1[] = "HTTP/1.0 200 OKrnServer: kHTTPd/0.1.6rnDate: ";
  126. #ifdef BENCHMARK
  127. static char HeaderPart1b[] ="HTTP/1.0 200 OK";
  128. #endif
  129. static char HeaderPart3[] = "rnContent-type: ";
  130. static char HeaderPart5[] = "rnLast-modified: ";
  131. static char HeaderPart7[] = "rnContent-length: ";
  132. static char HeaderPart9[] = "rnrn";
  133. #ifdef BENCHMARK
  134. /* In BENCHMARK-mode, just send the bare essentials */
  135. void SendHTTPHeader(struct http_request *Request)
  136. {
  137. struct msghdr msg;
  138. mm_segment_t oldfs;
  139. struct iovec iov[9];
  140. int  len,len2;
  141. EnterFunction("SendHTTPHeader");
  142. msg.msg_name     = 0;
  143. msg.msg_namelen  = 0;
  144. msg.msg_iov  = &iov[0];
  145. msg.msg_iovlen   = 6;
  146. msg.msg_control  = NULL;
  147. msg.msg_controllen = 0;
  148. msg.msg_flags    = 0;  /* Synchronous for now */
  149. iov[0].iov_base = HeaderPart1b;
  150. iov[0].iov_len  = 15;
  151. iov[1].iov_base = HeaderPart3;
  152. iov[1].iov_len  = 16;
  153. iov[2].iov_base = Request->MimeType;
  154. iov[2].iov_len  = Request->MimeLength;
  155. iov[3].iov_base = HeaderPart7;
  156. iov[3].iov_len  = 18;
  157. sprintf(Request->LengthS,"%i",Request->FileLength);
  158. iov[4].iov_base = Request->LengthS;
  159. iov[4].iov_len  = strlen(Request->LengthS);
  160. iov[5].iov_base = HeaderPart9;
  161. iov[5].iov_len  = 4;
  162. len2=15+16+18+iov[2].iov_len+iov[4].iov_len+4;
  163. len = 0;
  164. oldfs = get_fs(); set_fs(KERNEL_DS);
  165. len = sock_sendmsg(Request->sock,&msg,len2);
  166. set_fs(oldfs);
  167. return;
  168. }
  169. #else
  170. void SendHTTPHeader(struct http_request *Request)
  171. {
  172. struct msghdr msg;
  173. mm_segment_t oldfs;
  174. struct iovec iov[9];
  175. int  len,len2;
  176. __kernel_size_t slen;
  177. EnterFunction("SendHTTPHeader");
  178. msg.msg_name     = 0;
  179. msg.msg_namelen  = 0;
  180. msg.msg_iov  = &(iov[0]);
  181. msg.msg_iovlen   = 9;
  182. msg.msg_control  = NULL;
  183. msg.msg_controllen = 0;
  184. msg.msg_flags    = 0;  /* Synchronous for now */
  185. iov[0].iov_base = HeaderPart1;
  186. iov[0].iov_len  = 45;
  187. iov[1].iov_base = CurrentTime;
  188. iov[1].iov_len  = 29;
  189. iov[2].iov_base = HeaderPart3;
  190. iov[2].iov_len  = 16;
  191. iov[3].iov_base = Request->MimeType;
  192. iov[3].iov_len  = Request->MimeLength;
  193. iov[4].iov_base = HeaderPart5;
  194. iov[4].iov_len  = 17;
  195. iov[5].iov_base = &(Request->TimeS[0]);
  196. iov[5].iov_len  = 29;
  197. iov[6].iov_base = HeaderPart7;
  198. iov[6].iov_len  = 18;
  199. iov[7].iov_base = &(Request->LengthS[0]);
  200. slen = strlen(Request->LengthS); 
  201. iov[7].iov_len  = slen;
  202. iov[8].iov_base = HeaderPart9;
  203. iov[8].iov_len  = 4;
  204. len2=45+2*29+16+17+18+slen+4+iov[3].iov_len;
  205. len = 0;
  206. oldfs = get_fs(); set_fs(KERNEL_DS);
  207. len = sock_sendmsg(Request->sock,&msg,len2);
  208. set_fs(oldfs);
  209. LeaveFunction("SendHTTPHeader");
  210. return;
  211. }
  212. #endif
  213. /* 
  214. Parse a HTTP-header. Be careful for buffer-overflows here, this is the most important
  215. place for this, since the remote-user controls the data.
  216. */
  217. void ParseHeader(char *Buffer,const int length, struct http_request *Head)
  218. {
  219. char *Endval,*EOL,*tmp;
  220. EnterFunction("ParseHeader");
  221. Endval = Buffer + length;
  222. /* We want to parse only the first header if multiple headers are present */
  223. tmp = strstr(Buffer,"rnrn"); 
  224. if (tmp!=NULL)
  225.     Endval = tmp;
  226. while (Buffer<Endval)
  227. {
  228. if (isspace(Buffer[0]))
  229. {
  230. Buffer++;
  231. continue;
  232. }
  233. EOL=strchr(Buffer,'n');
  234. if (EOL==NULL) EOL=Endval;
  235. if (EOL-Buffer<4) 
  236. {
  237. Buffer++;
  238. continue;
  239. }
  240. if (strncmp("GET ",Buffer,4)==0)
  241. {
  242. int PrefixLen;
  243. Buffer+=4;
  244. tmp=strchr(Buffer,' ');
  245. if (tmp==0) 
  246. {
  247. tmp=EOL-1;
  248. Head->HTTPVER = 9;
  249. } else
  250. Head->HTTPVER = 10;
  251. if (tmp>Endval) continue;
  252. strncpy(Head->FileName,sysctl_khttpd_docroot,sizeof(Head->FileName));
  253. PrefixLen = strlen(sysctl_khttpd_docroot);
  254. Head->FileNameLength = min_t(unsigned int, 255, tmp - Buffer + PrefixLen);
  255. strncat(Head->FileName,Buffer,min_t(unsigned int, 255 - PrefixLen, tmp - Buffer));
  256. Buffer=EOL+1;
  257. #ifdef BENCHMARK
  258. break;
  259. #endif
  260. continue;
  261. }
  262. #ifndef BENCHMARK
  263. if (strncmp("If-Modified-Since: ",Buffer,19)==0)
  264. {
  265. Buffer+=19;
  266. strncpy(Head->IMS,Buffer,min_t(unsigned int, 127,EOL-Buffer-1));
  267. Buffer=EOL+1;
  268. continue;
  269. }
  270. if (strncmp("User-Agent: ",Buffer,12)==0)
  271. {
  272. Buffer+=12;
  273. strncpy(Head->Agent,Buffer,min_t(unsigned int, 127,EOL-Buffer-1));
  274. Buffer=EOL+1;
  275. continue;
  276. }
  277. if (strncmp("Host: ",Buffer,6)==0)
  278. {
  279. Buffer+=6;
  280. strncpy(Head->Host,Buffer,min_t(unsigned int, 127,EOL-Buffer-1));
  281. Buffer=EOL+1;
  282. continue;
  283. }
  284. #endif
  285. Buffer = EOL+1;  /* Skip line */
  286. }
  287. LeaveFunction("ParseHeader");
  288. }