3 kHTTPd -- the next generation
5 RFC related functions (headers and stuff)
9 /****************************************************************
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 ****************************************************************/
27 #include <linux/kernel.h>
29 #include <linux/ctype.h>
30 #include <linux/errno.h>
31 #include <linux/malloc.h>
32 #include <linux/net.h>
33 #include <linux/sched.h>
34 #include <linux/skbuff.h>
35 #include <linux/unistd.h>
36 #include <linux/file.h>
37 #include <linux/smp_lock.h>
42 #include <asm/atomic.h>
43 #include <asm/semaphore.h>
44 #include <asm/processor.h>
45 #include <asm/uaccess.h>
48 #include "prototypes.h"
49 #include "structure.h"
53 #define KHTTPD_NUMMIMETYPES 40
55 static atomic_t MimeCount
;
60 char type
[64-sizeof(__u32
)-sizeof(__kernel_size_t
)];
64 static struct MimeType MimeTypes
[KHTTPD_NUMMIMETYPES
];
67 void AddMimeType(const char *Ident
,const char *Type
)
71 EnterFunction("AddMimeType");
75 (void)printk(KERN_ERR
"httpd: Only 4-byte mime-identifiers are accepted\n");
79 if (strlen(Type
)>(64-sizeof(__u32
)-sizeof(__kernel_size_t
) ) )
81 (void)printk(KERN_ERR
"httpd: Mime-string too long.\n");
87 /* FIXME: Need to lock-down all access to the mime-structure here */
88 /* For now, just don't add mime-types after initialisation */
91 MimeTypes
[atomic_read(&MimeCount
)].identifier
=*I
;
92 strncpy(MimeTypes
[atomic_read(&MimeCount
)].type
,Type
,(64-sizeof(__u32
)-sizeof(__kernel_size_t
)));
93 MimeTypes
[atomic_read(&MimeCount
)].len
= strlen(Type
);
95 atomic_inc(&MimeCount
);
96 LeaveFunction("AddMimeType");
100 char *ResolveMimeType(const char *File
,__kernel_size_t
*Len
)
103 The returned string is for READ ONLY, ownership of the memory is NOT
111 EnterFunction("ResolveMimeType");
118 filelen
= (int)strlen(File
);
125 /* The Merced-people are NOT going to like this! So this has to be fixed
129 I
=(__u32
*)(File
+pos
);
133 while (lc
<atomic_read(&MimeCount
))
135 if (MimeTypes
[lc
].identifier
== *I
)
137 *Len
= MimeTypes
[lc
].len
;
138 LeaveFunction("ResolveMimeType - success");
139 return MimeTypes
[lc
].type
;
144 if (sysctl_khttpd_sloppymime
)
146 *Len
= MimeTypes
[0].len
;
147 LeaveFunction("ResolveMimeType - unknown");
148 return MimeTypes
[0].type
;
152 LeaveFunction("ResolveMimeType - failure");
158 static char HeaderPart1
[] = "HTTP/1.0 200 OK\r\nServer: kHTTPd/0.1.6\r\nDate: ";
160 static char HeaderPart1b
[] ="HTTP/1.0 200 OK";
162 static char HeaderPart3
[] = "\r\nContent-type: ";
163 static char HeaderPart5
[] = "\r\nLast-modified: ";
164 static char HeaderPart7
[] = "\r\nContent-length: ";
165 static char HeaderPart9
[] = "\r\n\r\n";
168 /* In BENCHMARK-mode, just send the bare essentials */
169 void SendHTTPHeader(struct http_request
*Request
)
177 EnterFunction("SendHTTPHeader");
181 msg
.msg_iov
= &iov
[0];
183 msg
.msg_control
= NULL
;
184 msg
.msg_controllen
= 0;
185 msg
.msg_flags
= 0; /* Synchronous for now */
187 iov
[0].iov_base
= HeaderPart1b
;
189 iov
[1].iov_base
= HeaderPart3
;
191 iov
[2].iov_base
= Request
->MimeType
;
192 iov
[2].iov_len
= Request
->MimeLength
;
194 iov
[3].iov_base
= HeaderPart7
;
198 sprintf(Request
->LengthS
,"%i",Request
->FileLength
);
199 iov
[4].iov_base
= Request
->LengthS
;
200 iov
[4].iov_len
= strlen(Request
->LengthS
);
201 iov
[5].iov_base
= HeaderPart9
;
204 len2
=15+16+18+iov
[2].iov_len
+iov
[4].iov_len
+4;
210 oldfs
= get_fs(); set_fs(KERNEL_DS
);
211 len
= sock_sendmsg(Request
->sock
,&msg
,len2
);
218 void SendHTTPHeader(struct http_request
*Request
)
224 __kernel_size_t slen
;
226 EnterFunction("SendHTTPHeader");
230 msg
.msg_iov
= &(iov
[0]);
232 msg
.msg_control
= NULL
;
233 msg
.msg_controllen
= 0;
234 msg
.msg_flags
= 0; /* Synchronous for now */
236 iov
[0].iov_base
= HeaderPart1
;
238 iov
[1].iov_base
= CurrentTime
;
240 iov
[2].iov_base
= HeaderPart3
;
243 iov
[3].iov_base
= Request
->MimeType
;
244 iov
[3].iov_len
= Request
->MimeLength
;
246 iov
[4].iov_base
= HeaderPart5
;
248 iov
[5].iov_base
= &(Request
->TimeS
[0]);
250 iov
[6].iov_base
= HeaderPart7
;
252 iov
[7].iov_base
= &(Request
->LengthS
[0]);
253 slen
= strlen(Request
->LengthS
);
254 iov
[7].iov_len
= slen
;
255 iov
[8].iov_base
= HeaderPart9
;
258 len2
=45+2*29+16+17+18+slen
+4+iov
[3].iov_len
;
262 oldfs
= get_fs(); set_fs(KERNEL_DS
);
263 len
= sock_sendmsg(Request
->sock
,&msg
,len2
);
265 LeaveFunction("SendHTTPHeader");
276 Parse a HTTP-header. Be careful for buffer-overflows here, this is the most important
277 place for this, since the remote-user controls the data.
280 void ParseHeader(char *Buffer
,const int length
, struct http_request
*Head
)
282 char *Endval
,*EOL
,*tmp
;
284 EnterFunction("ParseHeader");
285 Endval
= Buffer
+ length
;
287 /* We want to parse only the first header if multiple headers are present */
288 tmp
= strstr(Buffer
,"\r\n\r\n");
293 while (Buffer
<Endval
)
295 if (isspace(Buffer
[0]))
302 EOL
=strchr(Buffer
,'\n');
304 if (EOL
==NULL
) EOL
=Endval
;
312 if (strncmp("GET ",Buffer
,4)==0)
317 tmp
=strchr(Buffer
,' ');
325 if (tmp
>Endval
) continue;
327 strncpy(Head
->FileName
,sysctl_khttpd_docroot
,sizeof(Head
->FileName
));
328 PrefixLen
= strlen(sysctl_khttpd_docroot
);
329 Head
->FileNameLength
= min(255,tmp
-Buffer
+PrefixLen
);
331 strncat(Head
->FileName
,Buffer
,min(255-PrefixLen
,tmp
-Buffer
));
340 if (strncmp("If-Modified-Since: ",Buffer
,19)==0)
344 strncpy(Head
->IMS
,Buffer
,min(127,EOL
-Buffer
-1));
350 if (strncmp("User-Agent: ",Buffer
,12)==0)
354 strncpy(Head
->Agent
,Buffer
,min(127,EOL
-Buffer
-1));
361 if (strncmp("Host: ",Buffer
,6)==0)
365 strncpy(Head
->Host
,Buffer
,min(127,EOL
-Buffer
-1));
371 Buffer
= EOL
+1; /* Skip line */
373 LeaveFunction("ParseHeader");