-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathhttp.c
124 lines (97 loc) · 3.61 KB
/
http.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
* http.c:
* Look for HTTP requests in buffers.
*
* We look for GET requests only, and only if the response is of type
* text/html.
*
* Copyright (c) 2003 Chris Lightfoot. All rights reserved.
* Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
*
*/
static const char rcsid[] = "$Id: http.c,v 1.1 2003/08/12 14:14:15 chris Exp $";
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "driftnet.h"
/* find_http_req DATA LEN FOUND FOUNDLEN
* Look for an HTTP request and response in buffer DATA of length LEN. The
* return value is a pointer into DATA suitable for a subsequent call to this
* function; *FOUND is either NULL, or a pointer to the start of an HTTP
* request; in the latter case, *FOUNDLEN is the length of the match
* containing enough information to obtain the URL. */
unsigned char *find_http_req(const unsigned char *data, const size_t len, unsigned char **http, size_t *httplen) {
unsigned char *req, *le, *blankline, *hosthdr;
#define remaining(x) (len - (data - (x)))
#define MAX_REQ 16384
/* HTTP requests look like:
*
* GET {path} HTTP/1.(0|1)\r\n
* header: value\r\n
* ...
* \r\n
*
* We may care about the Host: header in the request. */
if (len < 40)
return (unsigned char*)data;
if (!(req = memstr(data, len, (unsigned char*) "GET ", 4)))
return (unsigned char*)(data + len - 4);
/* Find the end of the request line. */
if (!(le = memstr(req + 4, remaining(req + 4), (unsigned char*) "\r\n", 2))) {
if (remaining(req + 4) > MAX_REQ)
return (unsigned char*)(req + 4);
else
return (unsigned char*)req;
}
/* Not enough space for a path. */
if (le < req + 5)
return le + 2;
/* Not an HTTP request, just a line starting GET.... */
if (memcmp(le - 9, " HTTP/1.", 8) || !strchr("01", (int)*(le - 1)))
return le + 2;
/* Find the end of the request headers. */
if (!(blankline = memstr(le + 2, remaining(le + 2), (unsigned char*) "\r\n\r\n", 4))) {
if (remaining(le + 2) > MAX_REQ)
return (unsigned char*)(data + len - 4);
else
return req;
}
if (memcmp(req + 4, "http://", 7) == 0)
/* Probably a cache request; in any case, don't need to look for a Host:. */
goto found;
/* Is there a Host: header? */
if (!(hosthdr = memstr(le, blankline - le + 2, (unsigned char*) "\r\nHost: ", 8))) {
return blankline + 4;
}
found:
*http = req;
*httplen = blankline - req;
return blankline + 4;
}
void dispatch_http_req(const char *mname, const unsigned char *data, const size_t len) {
char *url;
const char *path, *host;
int pathlen, hostlen;
const unsigned char *p;
if (!(p = memstr(data, len, (unsigned char*) "\r\n", 2)))
return;
path = (const char*)(data + 4);
pathlen = (p - 9) - (unsigned char*)path;
if (memcmp(path, "http://", 7) == 0) {
url = malloc(pathlen + 1);
sprintf(url, "%.*s", pathlen, path);
} else {
if (!(p = memstr(p, len - (p - data), (unsigned char*) "\r\nHost: ", 8)))
return;
host = (const char*)(p + 8);
if (!(p = memstr(p + 8, len - (p + 8 - data), (unsigned char*) "\r\n", 2)))
return;
hostlen = p - (const unsigned char*)host;
if (hostlen == 0)
return;
url = malloc(hostlen + pathlen + 9);
sprintf(url, "http://%.*s%.*s", hostlen, host, pathlen, path);
}
fprintf(stderr, "\n\n %s\n\n", url);
free(url);
}