1 /** @file
2
3 A brief file description
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
23
24 /****************************************************************************
25
26 load_http_hdr.cc
27
28 Description:
29
30 Opens a file with a dbx dump of an http hdr and loads it
31
32
33 ****************************************************************************/
34
35 /***************************************************************************
36 * USAGE NOTE: This program was originally built for reading TS 3.0.X &
37 * TS 3.5.X header dumps. These data structures were always contiguous.
38 * TS 4.0.X and later have completely redesigned data structures that
39 * are more complicated but much faster. This program has been adapted
40 * read headers that have been unmarshalled from cache, in which
41 * case they are contiguous. It's conversion is in a half baked
42 * state and is therefore not useful for must purposes.
43 ***************************************************************************/
44
45 #include "HdrHeap.h"
46 #include "MIME.h"
47 #include "HTTP.h"
48 #include "tscore/Tokenizer.h"
49 #include "tscore/Diags.h"
50 #include <stdio.h>
51 #include <errno.h>
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <fcntl.h>
55 #include <unistd.h>
56
57 void *low_load_addr = NULL;
58 void *high_load_addr = NULL;
59 int heap_load_size = 0;
60 int marshalled = 0;
61
62 // Diags *diags;
63
64 enum hdr_type {
65 UNKNOWN_HDR,
66 REQUEST_HDR,
67 RESPONSE_HDR,
68 HTTP_INFO_HDR,
69 RAW_MBUFFER,
70 };
71
72 char *
load_string(const char * s,int len,int offset)73 load_string(const char *s, int len, int offset)
74 {
75 const char *copy_from;
76 if (marshalled == 0 && s > low_load_addr && s + len < high_load_addr) {
77 copy_from = s + offset;
78 } else if (marshalled && ((unsigned int)s) + len < (unsigned int)heap_load_size) {
79 copy_from = s + offset;
80 } else {
81 copy_from = "<BAD>";
82 len = strlen(copy_from);
83 }
84 char *r = (char *)ats_malloc(len + 1);
85 memcpy(r, copy_from, len);
86 r[len] = '\0';
87 return r;
88 }
89
90 void
process_http_hdr_impl(HdrHeapObjImpl * obj,int offset)91 process_http_hdr_impl(HdrHeapObjImpl *obj, int offset)
92 {
93 char *s;
94 HTTPHdrImpl *hhdr = (HTTPHdrImpl *)obj;
95
96 if (hhdr->m_polarity == HTTP_TYPE_REQUEST) {
97 printf(" is a request hdr\n");
98 s = load_string(hhdr->u.req.m_ptr_method, hhdr->u.req.m_len_method, offset);
99 printf(" method: %s\n", s);
100 ats_free(s);
101 } else if (hhdr->m_polarity == HTTP_TYPE_RESPONSE) {
102 printf(" is a response hdr\n");
103 printf(" status code: %d\n", (int)hhdr->u.resp.m_status);
104 s = load_string(hhdr->u.resp.m_ptr_reason, hhdr->u.resp.m_len_reason, offset);
105 printf(" method: %s\n", s);
106 ats_free(s);
107 }
108 }
109
110 void
process_mime_block_impl(MIMEFieldBlockImpl * mblock,int offset)111 process_mime_block_impl(MIMEFieldBlockImpl *mblock, int offset)
112 {
113 printf(" Processing mime_flock_impl - freetop %d\n", mblock->m_freetop);
114 int freetop;
115 if (mblock->m_freetop <= MIME_FIELD_BLOCK_SLOTS) {
116 freetop = mblock->m_freetop;
117 } else {
118 freetop = MIME_FIELD_BLOCK_SLOTS;
119 }
120
121 char *n, *v;
122 for (unsigned int i = 0; i < freetop; i++) {
123 MIMEField *f = &mblock->m_field_slots[i];
124 if (hdrtoken_is_valid_wks_idx(f->m_wks_idx)) {
125 n = ats_strdup(hdrtoken_index_to_wks(f->m_wks_idx));
126 } else {
127 n = load_string(f->m_ptr_name, f->m_len_name, offset);
128 }
129 v = load_string(f->m_ptr_value, f->m_len_value, offset);
130 printf(" (%d) %s: %s\n", i, n, v);
131 ats_free(n);
132 ats_free(v);
133 }
134 }
135
136 void
process_mime_hdr_impl(HdrHeapObjImpl * obj,int offset)137 process_mime_hdr_impl(HdrHeapObjImpl *obj, int offset)
138 {
139 MIMEHdrImpl *mhdr = (MIMEHdrImpl *)obj;
140
141 process_mime_block_impl(&mhdr->m_first_fblock, offset);
142 }
143
144 void
loop_over_heap_objs(HdrHeap * hdr_heap,int offset)145 loop_over_heap_objs(HdrHeap *hdr_heap, int offset)
146 {
147 char *buffer_end;
148
149 printf("Looping over HdrHeap objects @ 0x%X\n", hdr_heap);
150
151 if (hdr_heap->m_magic == HDR_BUF_MAGIC_MARSHALED) {
152 printf(" marshalled heap - size %d\n", hdr_heap->m_size);
153 hdr_heap->m_data_start = ((char *)hdr_heap) + ROUND(sizeof(HdrHeap), HDR_PTR_SIZE);
154 hdr_heap->m_free_start = ((char *)hdr_heap) + hdr_heap->m_size;
155 } else {
156 buffer_end = hdr_heap->m_free_start;
157 }
158
159 printf(" heap len is %d bytes\n", hdr_heap->m_free_start - hdr_heap->m_data_start);
160
161 char *obj_data = hdr_heap->m_data_start;
162 while (obj_data < hdr_heap->m_free_start) {
163 HdrHeapObjImpl *obj = (HdrHeapObjImpl *)obj_data;
164
165 switch (obj->m_type) {
166 case HDR_HEAP_OBJ_HTTP_HEADER:
167 printf(" HDR_HEAP_OBJ_HTTP_HEADER %d bytes\n", obj->m_length);
168 process_http_hdr_impl(obj, offset);
169 break;
170 case HDR_HEAP_OBJ_URL:
171 printf(" HDR_HEAP_OBJ_URL %d bytes\n", obj->m_length);
172 break;
173 case HDR_HEAP_OBJ_FIELD_BLOCK:
174 printf(" HDR_HEAP_OBJ_FIELD_BLOCK %d bytes\n", obj->m_length);
175 break;
176 case HDR_HEAP_OBJ_MIME_HEADER:
177 printf(" HDR_HEAP_OBJ_MIME_HEADER %d bytes\n", obj->m_length);
178 process_mime_hdr_impl(obj, offset);
179 break;
180 case HDR_HEAP_OBJ_EMPTY:
181 printf(" HDR_HEAP_OBJ_EMPTY %d bytes\n", obj->m_length);
182 break;
183 default:
184 printf(" OBJ UNKNOWN (%d) %d bytes\n", obj->m_type, obj->m_length);
185 }
186
187 if (obj->m_length == 0) {
188 printf(" ERROR zero length object\n");
189 break;
190 }
191 obj_data = obj_data + obj->m_length;
192 }
193 }
194
195 void
load_buffer(int fd,hdr_type h_type)196 load_buffer(int fd, hdr_type h_type)
197 {
198 struct stat s_info;
199
200 if (fstat(fd, &s_info) < 0) {
201 fprintf(stderr, "Failed to stat data file : %s\n", strerror(errno));
202 exit(1);
203 }
204
205 char *file_buf = (char *)ats_malloc(sizeof(char) * (s_info.st_size + 1));
206 file_buf[s_info.st_size] = '\0';
207
208 // Read in the entire file
209 int bytes_to_read = s_info.st_size;
210 while (bytes_to_read > 0) {
211 int done = read(fd, file_buf, bytes_to_read);
212
213 if (done < 0) {
214 fprintf(stderr, "Failed to read data file : %s\n", strerror(errno));
215 exit(1);
216 } else if (done == 0) {
217 fprintf(stderr, "EOF encounted\n");
218 exit(1);
219 }
220
221 bytes_to_read -= done;
222 }
223
224 Tokenizer line_tok("\n");
225 Tokenizer el_tok(" \t");
226
227 int num_lines = line_tok.Initialize(file_buf);
228 int num_el = el_tok.Initialize(line_tok[0]);
229
230 if (num_el < 3) {
231 fprintf(stderr, "Corrupted data file\n");
232 exit(1);
233 }
234
235 void *old_addr = NULL;
236 if (sscanf(el_tok[0], "%x:", &old_addr) != 1) {
237 fprintf(stderr, "Corrupted data file\n");
238 exit(1);
239 }
240 low_load_addr = old_addr;
241
242 int hdr_size;
243 if (sscanf(el_tok[4], "%x", &hdr_size) != 1) {
244 fprintf(stderr, "Corrupted data file\n");
245 exit(1);
246 }
247 hdr_size = (num_lines * 16);
248 heap_load_size = hdr_size;
249
250 char *hdr_heap = (char *)ats_malloc(hdr_size);
251 int bytes_read = 0;
252 int cur_line = 0;
253
254 while (cur_line < num_lines && bytes_read < hdr_size) {
255 int *cur_ptr;
256 num_el = el_tok.Initialize(line_tok[cur_line]);
257
258 if (sscanf(el_tok[0], "%x:", &high_load_addr) != 1) {
259 fprintf(stderr, "Corrupted data file\n");
260 exit(1);
261 }
262 high_load_addr = ((char *)high_load_addr) + (num_el * 4);
263
264 int el;
265 for (int i = 1; i < num_el; i++) {
266 if (sscanf(el_tok[i], "%x", &el) != 1) {
267 fprintf(stderr, "Corrupted data file\n");
268 exit(1);
269 }
270 cur_ptr = (int *)(hdr_heap + bytes_read);
271 *cur_ptr = el;
272 bytes_read += 4;
273 }
274 cur_line++;
275 }
276
277 HdrHeap *my_heap = (HdrHeap *)hdr_heap;
278 int offset = hdr_heap - (char *)old_addr;
279
280 // Patch up some values
281 if (my_heap->m_magic == HDR_BUF_MAGIC_MARSHALED) {
282 // HdrHeapObjImpl* obj;
283 // my_heap->unmarshal(hdr_size, HDR_HEAP_OBJ_HTTP_HEADER, &obj, NULL);
284 marshalled = 1;
285 offset = (int)hdr_heap;
286 } else {
287 my_heap->m_free_start = my_heap->m_free_start + offset;
288 my_heap->m_data_start = my_heap->m_data_start + offset;
289 my_heap->m_ronly_heap[0].m_heap_start = my_heap->m_ronly_heap[0].m_heap_start + offset;
290 }
291 loop_over_heap_objs(my_heap, offset);
292 }
293
294 int
main(int argc,const char * argv[])295 main(int argc, const char *argv[])
296 {
297 hdr_type h_type = UNKNOWN_HDR;
298
299 http_init();
300 diags = new Diags(NULL, NULL);
301 if (argc != 3) {
302 fprintf(stderr, "Usage: %s req|res <file>\n", argv[0]);
303 exit(1);
304 }
305
306 if (strcasecmp(argv[1], "req") == 0) {
307 h_type = REQUEST_HDR;
308 } else if (strcasecmp(argv[1], "resp") == 0) {
309 h_type = RESPONSE_HDR;
310 } else if (strcasecmp(argv[1], "hinfo") == 0) {
311 h_type = HTTP_INFO_HDR;
312 } else if (strcasecmp(argv[1], "mbuf") == 0) {
313 h_type = RAW_MBUFFER;
314 } else {
315 fprintf(stderr, "Usage: %s req|resp|hinfo|mbuf <file>\n", argv[0]);
316 exit(1);
317 }
318
319 int fd = open(argv[2], O_RDONLY);
320
321 if (fd < 0) {
322 fprintf(stderr, "Could not open file %s : %s\n", argv[2], strerror(errno));
323 exit(1);
324 }
325 load_buffer(fd, h_type);
326
327 return 0;
328 }
329