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