Branch data Line data Source code
1 : : // $Id:$
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <assert.h>
9 : : #include <stdlib.h>
10 : :
11 : : #include "Event.h"
12 : : #include "Net.h"
13 : : #include "UDP_Rewriter.h"
14 : :
15 : : #define MSG_PREFIX "UDP trace rewriter: "
16 : : #define DEBUG_MSG_A(x...)
17 : : // #define DEBUG_MSG_A DEBUG_MSG
18 : :
19 : :
20 : : UDP_Rewriter::UDP_Rewriter(Analyzer* arg_analyzer, int arg_MTU,
21 : 0 : PacketDumper* arg_dumper)
22 : : {
23 : 0 : analyzer = arg_analyzer;
24 : 0 : MTU = arg_MTU;
25 : 0 : dumper = arg_dumper;
26 : 0 : packets_rewritten = 0;
27 : 0 : current_packet = next_packet = 0;
28 : :
29 [ # # # # ]: 0 : if ( anonymize_ip_addr )
30 : : {
31 : : anon_addr[0] = anonymize_ip(to_v4_addr(analyzer->Conn()->OrigAddr()),
32 : 0 : ORIG_ADDR);
33 : : anon_addr[1] = anonymize_ip(to_v4_addr(analyzer->Conn()->RespAddr()),
34 : 0 : RESP_ADDR);
35 : : }
36 : : else
37 : 0 : anon_addr[0] = anon_addr[1] = 0;
38 : 0 : }
39 : :
40 : 0 : void UDP_Rewriter::Done()
41 : : {
42 : 0 : }
43 : :
44 : 0 : UDP_Rewriter::~UDP_Rewriter()
45 : : {
46 [ # # ][ # # ]: 0 : delete current_packet;
[ # # ]
47 [ # # ][ # # ]: 0 : }
[ # # ]
48 : :
49 : 0 : void UDP_Rewriter::WriteData(int is_orig, int len, const u_char* data)
50 : : {
51 : 0 : DoWriteData(is_orig, len, data);
52 : 0 : }
53 : :
54 : 0 : void UDP_Rewriter::DoWriteData(int is_orig, int len, const u_char* data)
55 : : {
56 : : struct pcap_pkthdr* hdr;
57 : 0 : int length = len;
58 : 0 : ipaddr32_t src = 0, dst = 0;
59 : :
60 : 0 : current_packet->AppendData(data,len);
61 : : // Mark data to be written.
62 : 0 : current_packet->SetModified();
63 : 0 : }
64 : :
65 : : // Compose the packet so it can be written.
66 : : // Compute UDP/IP checksums, lengths, addresses.
67 : : int UDP_TracePacket::BuildPacket(struct pcap_pkthdr*& hdr,
68 : : const u_char*& arg_pkt, int& length,
69 : 0 : ipaddr32_t anon_src, ipaddr32_t anon_dst)
70 : : {
71 : 0 : struct ip* ip = (struct ip*) (pkt + ip_offset);
72 : 0 : struct udphdr* up = (struct udphdr*) (pkt + udp_offset);
73 : 0 : uint32 sum = 0;
74 : :
75 : : // Fix IP addresses before computing the UDP checksum
76 [ # # ]: 0 : if ( anonymize_ip_addr )
77 : : {
78 : 0 : ip->ip_src.s_addr = anon_src;
79 : 0 : ip->ip_dst.s_addr = anon_dst;
80 : : }
81 : :
82 : : // Create the IP header.
83 : 0 : ip->ip_off = 0;
84 : 0 : ip->ip_sum = 0;
85 : 0 : ip->ip_hl = (udp_offset - ip_offset) >> 2;
86 : 0 : ip->ip_len = htons(buffer_offset - ip_offset);
87 : 0 : ip->ip_off = 0; // DF = 0, MF = 0, offset = 0
88 : 0 : ip->ip_sum = 0;
89 : : ip->ip_sum = 0xffff - ones_complement_checksum((const void*) ip,
90 : 0 : (udp_offset-ip_offset), sum);
91 : :
92 : 0 : pcap_hdr.caplen = pcap_hdr.len = buffer_offset;
93 : :
94 : 0 : hdr = &pcap_hdr;
95 : 0 : arg_pkt = pkt;
96 : 0 : length = buffer_offset;
97 : :
98 : : // Create the UDP header.
99 : 0 : up->uh_ulen = htons(buffer_offset - udp_offset);
100 : 0 : up->uh_sum = 0;
101 : 0 : up->uh_sum = 0xffff - udp_checksum(ip, up, buffer_offset - udp_offset);
102 : :
103 : : // Create the pcap header.
104 : : //
105 : : // The below works around a potential type incompatibility
106 : : // on systems where pcap's timeval is different from the
107 : : // system-wide one. --cpk
108 : : //
109 : 0 : timeval tv_tmp = double_to_timeval(timestamp);
110 : 0 : pcap_hdr.ts.tv_sec = tv_tmp.tv_sec;
111 : 0 : pcap_hdr.ts.tv_usec = tv_tmp.tv_usec;
112 : 0 : pcap_hdr.caplen = pcap_hdr.len = buffer_offset;
113 : :
114 : 0 : hdr = &pcap_hdr;
115 : 0 : arg_pkt = pkt;
116 : 0 : length = buffer_offset;
117 : :
118 : 0 : return 1;
119 : : }
120 : :
121 : : void UDP_Rewriter::NextPacket(int is_orig, double t,
122 : : const struct pcap_pkthdr* pcap_hdr,
123 : : const u_char* pcap_pkt, int hdr_size,
124 : 0 : const struct ip* ip, const struct udphdr* up)
125 : : {
126 : 0 : unsigned int ip_hdr_len = ip->ip_hl * 4;
127 : :
128 : : // Cache the packet ....
129 : : UDP_TracePacket* p = new UDP_TracePacket(this, t, is_orig,
130 : : pcap_hdr, /*MTU */ 1024,
131 : 0 : hdr_size + ip_hdr_len + sizeof(struct udphdr));
132 : :
133 [ # # ]: 0 : if ( ! p->AppendLinkHeader(pcap_pkt, hdr_size) )
134 : 0 : internal_error(MSG_PREFIX "cannot append headers -- check MTU");
135 : :
136 [ # # ]: 0 : if ( ! p->AppendIPHeader((const u_char*) ip, sizeof(*ip)) )
137 : 0 : internal_error(MSG_PREFIX "cannot append headers -- check MTU");
138 : :
139 [ # # ]: 0 : if ( ! p->AppendUDPHeader((const u_char*) up, sizeof(*up)) )
140 : 0 : internal_error(MSG_PREFIX "cannot append headers -- check MTU");
141 : :
142 : : // We only ever use one packet in UDP.
143 : : // ### This is potentially a leak.
144 : 0 : next_packet = current_packet = p;
145 : 0 : }
146 : :
147 : 0 : void UDP_Rewriter::Push(int)
148 : : {
149 : 0 : internal_error("UDP_Rewriter::Push not implemented");
150 : : }
151 : :
152 : 0 : void UDP_Rewriter::AbortPackets(int)
153 : : {
154 : 0 : internal_error("UDP_Rewriter::AbortPackets not implemented");
155 : : }
156 : :
157 : 0 : unsigned int UDP_Rewriter::ReserveSlot()
158 : : {
159 : 0 : internal_error("UDP_Rewriter::ReserveSlot not implemented");
160 : : return 0;
161 : : }
162 : :
163 : 0 : int UDP_Rewriter::SeekSlot(unsigned int)
164 : : {
165 : 0 : internal_error("UDP_Rewriter::SeekSlot not implemented");
166 : : return 0;
167 : : }
168 : :
169 : 0 : int UDP_Rewriter::ReturnFromSlot()
170 : : {
171 : 0 : internal_error("UDP_Rewriter::ReturnFromSlot not implemented");
172 : : return 0;
173 : : }
174 : 0 : int UDP_Rewriter::ReleaseSlot(unsigned int)
175 : : {
176 : 0 : internal_error("UDP_Rewriter::ReleaseSlot not implemented");
177 : : return 0;
178 : : }
179 : :
180 : 0 : int UDP_Rewriter::LeaveAddrInTheClear(int is_orig)
181 : : {
182 : 0 : internal_error("UDP_Rewriter::LeaveAddrInTheClear not implemented");
183 : : return 0;
184 : : }
185 : :
186 : 0 : void UDP_Rewriter::CommitPackets(int commit)
187 : : {
188 [ # # ][ # # ]: 0 : if ( current_packet && current_packet->IsModified() )
[ # # ]
189 : : {
190 : 0 : ipaddr32_t anon_src = 0, anon_dst = 0;
191 : :
192 [ # # ]: 0 : if ( current_packet->IsOrig() )
193 : : {
194 : 0 : anon_src = anon_addr[0];
195 : 0 : anon_dst = anon_addr[1];
196 : : }
197 : : else
198 : : {
199 : 0 : anon_src = anon_addr[1];
200 : 0 : anon_dst = anon_addr[0];
201 : : }
202 : :
203 : : struct pcap_pkthdr* hdr;
204 : : const u_char* pkt;
205 : : int len;
206 : 0 : current_packet->BuildPacket(hdr, pkt, len, anon_src, anon_dst);
207 : :
208 : 0 : dumper->DumpPacket(hdr, pkt, hdr->caplen);
209 : : }
210 : :
211 [ # # ]: 0 : delete current_packet;
212 : 0 : next_packet = current_packet = 0;
213 : :
214 : 0 : ++packets_rewritten;
215 : 0 : }
216 : :
217 : : UDP_TracePacket::UDP_TracePacket(UDP_Rewriter* arg_trace_rewriter,
218 : : double t, int arg_is_orig,
219 : : const struct pcap_pkthdr* arg_hdr,
220 : 0 : int MTU, int initial_size)
221 : : {
222 : 0 : trace_rewriter = arg_trace_rewriter;
223 : 0 : pcap_hdr = *arg_hdr;
224 : : // packet_seq = arg_packet_seq;
225 : 0 : timestamp = t;
226 : 0 : is_orig = arg_is_orig;
227 : 0 : mtu = MTU;
228 : 0 : buffer_size = initial_size;
229 : 0 : buffer_offset = 0;
230 : :
231 : 0 : pkt = new u_char[buffer_size];
232 : :
233 : 0 : ip_offset = udp_offset = data_offset = -1;
234 : :
235 : 0 : reuse = 0;
236 : 0 : on_hold = 0;
237 : 0 : modified = 0;
238 : 0 : seq_gap = 0;
239 : :
240 : 0 : packet_val = 0;
241 : 0 : packet_val = PacketVal();
242 : 0 : }
243 : :
244 : 0 : UDP_TracePacket::~UDP_TracePacket()
245 : : {
246 : 0 : packet_val->SetOrigin(0);
247 : 0 : Unref(packet_val);
248 [ # # # # ]: 0 : delete [] pkt;
[ # # ]
249 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
250 : :
251 : 0 : RecordVal* UDP_TracePacket::PacketVal()
252 : : {
253 [ # # ]: 0 : if ( packet_val )
254 : 0 : Ref(packet_val);
255 : : else
256 : : {
257 : 0 : packet_val = new RecordVal(packet_type);
258 : 0 : packet_val->Assign(0, TraceRewriter()->GetAnalyzer()->BuildConnVal());
259 : 0 : packet_val->Assign(1, new Val(IsOrig(), TYPE_BOOL));
260 : 0 : packet_val->Assign(2, new Val(TimeStamp(), TYPE_TIME));
261 : 0 : packet_val->SetOrigin(this);
262 : : }
263 : :
264 : 0 : return packet_val;
265 : : }
266 : :
267 : 0 : int UDP_TracePacket::AppendLinkHeader(const u_char* chunk, int len)
268 : : {
269 [ # # ][ # # ]: 0 : if ( ip_offset >= 0 && ip_offset != buffer_offset )
270 : 0 : internal_error(MSG_PREFIX "link header must be appended before IP header");
271 : :
272 [ # # ]: 0 : if ( ! Append(chunk, len) )
273 : 0 : return 0;
274 : :
275 : 0 : ip_offset = buffer_offset;
276 : 0 : return 1;
277 : : }
278 : :
279 : 0 : int UDP_TracePacket::AppendIPHeader(const u_char* chunk, int len)
280 : : {
281 [ # # ][ # # ]: 0 : if ( udp_offset >= 0 && udp_offset != buffer_offset )
282 : 0 : internal_error(MSG_PREFIX "IP header must be appended before udp header");
283 : :
284 [ # # ]: 0 : if ( ! Append(chunk, len) )
285 : 0 : return 0;
286 : :
287 : 0 : udp_offset = buffer_offset;
288 : 0 : return 1;
289 : : }
290 : :
291 : 0 : int UDP_TracePacket::AppendUDPHeader(const u_char* chunk, int len)
292 : : {
293 [ # # ][ # # ]: 0 : if ( data_offset >= 0 && data_offset != buffer_offset )
294 : 0 : internal_error(MSG_PREFIX "tcp header must be appended before payload");
295 : :
296 [ # # ]: 0 : if ( udp_offset == buffer_offset )
297 : : { // first UDP header chunk
298 : 0 : int extra = (udp_offset - ip_offset) % 4;
299 [ # # ]: 0 : if ( extra )
300 : : {
301 : 0 : DEBUG_MSG(MSG_PREFIX "padding IP header");
302 [ # # ]: 0 : if ( ! AppendIPHeader(0, 4 - extra) )
303 : 0 : return 0;
304 : : }
305 : : }
306 : :
307 [ # # ]: 0 : if ( ! Append(chunk, len) )
308 : 0 : return 0;
309 : :
310 : 0 : data_offset = buffer_offset;
311 : 0 : return 1;
312 : : }
313 : :
314 : 0 : int UDP_TracePacket::AppendData(const u_char* chunk, int len)
315 : : {
316 : : // All headers must be appended before any data.
317 [ # # ][ # # ]: 0 : ASSERT(ip_offset >= 0 && udp_offset >= 0 && data_offset >= 0);
[ # # ][ # # ]
318 : :
319 [ # # ]: 0 : if ( data_offset == buffer_offset )
320 : : { // first data chunk
321 : 0 : int extra = (data_offset - udp_offset) % 4;
322 [ # # ]: 0 : if ( extra )
323 : : {
324 [ # # ]: 0 : if ( ! AppendUDPHeader(0, 4 - extra) )
325 : 0 : return 0;
326 : : }
327 : : }
328 : :
329 [ # # ]: 0 : if ( ! Append(chunk, len) )
330 : 0 : return 0;
331 : :
332 : 0 : return 1;
333 : : }
334 : :
335 : 0 : int UDP_TracePacket::Append(const u_char* chunk, int len)
336 : : {
337 [ # # ]: 0 : if ( buffer_offset + len > buffer_size )
338 : : {
339 [ # # ]: 0 : if ( buffer_offset + len > mtu )
340 : 0 : return 0;
341 : :
342 : 0 : u_char* tmp = new u_char[mtu];
343 [ # # ]: 0 : for ( int i = 0 ; i < buffer_size; ++i )
344 : 0 : tmp[i] = pkt[i];
345 : :
346 [ # # ]: 0 : delete [] pkt;
347 : 0 : pkt = tmp;
348 : 0 : buffer_size = mtu;
349 : : }
350 : :
351 [ # # ]: 0 : ASSERT(buffer_offset + len <= buffer_size);
352 : :
353 [ # # ]: 0 : if ( chunk )
354 : 0 : memcpy(pkt + buffer_offset, chunk, len);
355 : : else
356 : : // Fill with 0.
357 : 0 : memset(pkt + buffer_offset, 0, len);
358 : :
359 : 0 : buffer_offset += len;
360 : :
361 : 0 : return 1;
362 [ + - ][ + - ]: 6 : }
|