Branch data Line data Source code
1 : : // $Id: Conn.cc 6219 2008-10-01 05:39:07Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include <ctype.h>
8 : :
9 : : #include "Net.h"
10 : : #include "NetVar.h"
11 : : #include "Conn.h"
12 : : #include "Event.h"
13 : : #include "Sessions.h"
14 : : #include "Logger.h"
15 : : #include "Timer.h"
16 : : #include "PIA.h"
17 : : #include "binpac.h"
18 : :
19 : 20278 : HashKey* ConnID::BuildConnKey() const
20 : : {
21 : : Key key;
22 : :
23 : : // Lookup up connection based on canonical ordering, which is
24 : : // the smaller of <src addr, src port> and <dst addr, dst port>
25 : : // followed by the other.
26 [ + + ][ + + ]: 20278 : if ( is_one_way ||
[ + + ]
27 : : addr_port_canon_lt(src_addr, src_port, dst_addr, dst_port) )
28 : : {
29 : 11326 : copy_addr(src_addr, key.ip1);
30 : 11326 : copy_addr(dst_addr, key.ip2);
31 : 11326 : key.port1 = src_port;
32 : 11326 : key.port2 = dst_port;
33 : : }
34 : : else
35 : : {
36 : 8952 : copy_addr(dst_addr, key.ip1);
37 : 8952 : copy_addr(src_addr, key.ip2);
38 : 8952 : key.port1 = dst_port;
39 : 8952 : key.port2 = src_port;
40 : : }
41 : :
42 : 20278 : return new HashKey(&key, sizeof(key));
43 : : }
44 : :
45 : : void ConnectionTimer::Init(Connection* arg_conn, timer_func arg_timer,
46 : 2048 : int arg_do_expire)
47 : : {
48 : 2048 : conn = arg_conn;
49 : 2048 : timer = arg_timer;
50 : 2048 : do_expire = arg_do_expire;
51 : 2048 : Ref(conn);
52 : 2048 : }
53 : :
54 : 2048 : ConnectionTimer::~ConnectionTimer()
55 : : {
56 [ - + ][ # # ]: 2048 : if ( conn->RefCnt() < 1 )
[ # # ]
57 : 0 : internal_error("reference count inconsistency in ~ConnectionTimer");
58 : :
59 : 2048 : conn->RemoveTimer(this);
60 : 2048 : Unref(conn);
61 [ + - ][ # # ]: 2048 : }
[ # # ]
62 : :
63 : 1509 : void ConnectionTimer::Dispatch(double t, int is_expire)
64 : : {
65 [ + + ][ - + ]: 1509 : if ( is_expire && ! do_expire )
66 : 1509 : return;
67 : :
68 : : // Remove ourselves from the connection's set of timers so
69 : : // it doesn't try to cancel us.
70 : 1506 : conn->RemoveTimer(this);
71 : :
72 [ - + ]: 1506 : (conn->*timer)(t);
73 : :
74 [ - + ]: 1506 : if ( conn->RefCnt() < 1 )
75 : 0 : internal_error("reference count inconsistency in ConnectionTimer::Dispatch");
76 : : }
77 : :
78 : 3 : IMPLEMENT_SERIAL(ConnectionTimer, SER_CONNECTION_TIMER);
79 : :
80 : 0 : bool ConnectionTimer::DoSerialize(SerialInfo* info) const
81 : : {
82 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_CONNECTION_TIMER, Timer);
83 : :
84 : : // We enumerate all the possible timer functions here ... This
85 : : // has to match the list is DoUnserialize()!
86 : 0 : char type = 0;
87 : :
88 [ # # ][ # # ]: 0 : if ( timer == timer_func(&Connection::DeleteTimer) )
[ # # ]
89 : 0 : type = 1;
90 [ # # ][ # # ]: 0 : else if ( timer == timer_func(&Connection::InactivityTimer) )
[ # # ]
91 : 0 : type = 2;
92 [ # # ][ # # ]: 0 : else if ( timer == timer_func(&Connection::StatusUpdateTimer) )
[ # # ]
93 : 0 : type = 3;
94 [ # # ][ # # ]: 0 : else if ( timer == timer_func(&Connection::RemoveConnectionTimer) )
[ # # ]
95 : 0 : type = 4;
96 : : else
97 : 0 : internal_error("unknown function in ConnectionTimer::DoSerialize()");
98 : :
99 [ # # ][ # # ]: 0 : return conn->Serialize(info) && SERIALIZE(type) && SERIALIZE(do_expire);
[ # # ]
100 : : }
101 : :
102 : 0 : bool ConnectionTimer::DoUnserialize(UnserialInfo* info)
103 : : {
104 [ # # ]: 0 : DO_UNSERIALIZE(Timer);
105 : :
106 : 0 : conn = Connection::Unserialize(info);
107 [ # # ]: 0 : if ( ! conn )
108 : 0 : return false;
109 : :
110 : : char type;
111 : :
112 [ # # ][ # # ]: 0 : if ( ! UNSERIALIZE(&type) || ! UNSERIALIZE(&do_expire) )
[ # # ]
113 : 0 : return false;
114 : :
115 [ # # # # : 0 : switch ( type ) {
# ]
116 : : case 1:
117 : 0 : timer = timer_func(&Connection::DeleteTimer);
118 : 0 : break;
119 : : case 2:
120 : 0 : timer = timer_func(&Connection::InactivityTimer);
121 : 0 : break;
122 : : case 3:
123 : 0 : timer = timer_func(&Connection::StatusUpdateTimer);
124 : 0 : break;
125 : : case 4:
126 : 0 : timer = timer_func(&Connection::RemoveConnectionTimer);
127 : 0 : break;
128 : : default:
129 : 0 : info->s->Error("unknown connection timer function");
130 : 0 : return false;
131 : : }
132 : :
133 : 0 : return true;
134 : : }
135 : :
136 : : unsigned int Connection::total_connections = 0;
137 : : unsigned int Connection::current_connections = 0;
138 : : unsigned int Connection::external_connections = 0;
139 : :
140 : 3 : IMPLEMENT_SERIAL(Connection, SER_CONNECTION);
141 : :
142 : 1627 : Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id)
143 : : {
144 : 1627 : sessions = s;
145 : 1627 : key = k;
146 : 1627 : start_time = last_time = t;
147 : :
148 : 1627 : copy_addr(id->src_addr, orig_addr);
149 : 1627 : copy_addr(id->dst_addr, resp_addr);
150 : 1627 : orig_port = id->src_port;
151 : 1627 : resp_port = id->dst_port;
152 : 1627 : proto = TRANSPORT_UNKNOWN;
153 : :
154 : 1627 : conn_val = 0;
155 : 1627 : orig_endp = resp_endp = 0;
156 : 1627 : login_conn = 0;
157 : :
158 : 1627 : is_active = 1;
159 : 1627 : skip = 0;
160 : 1627 : weird = 0;
161 : 1627 : persistent = 0;
162 : :
163 : 1627 : suppress_event = 0;
164 : :
165 : 1627 : record_contents = record_packets = 1;
166 : :
167 : 1627 : timers_canceled = 0;
168 : 1627 : inactivity_timeout = 0;
169 : 1627 : installed_status_timer = 0;
170 : :
171 : 1627 : finished = 0;
172 : :
173 : 1627 : hist_seen = 0;
174 : 1627 : history = "";
175 : :
176 : 1627 : root_analyzer = 0;
177 : 1627 : primary_PIA = 0;
178 : :
179 : 1627 : ++current_connections;
180 : 1627 : ++total_connections;
181 : :
182 : 1627 : TimerMgr::Tag* tag = current_iosrc->GetCurrentTag();
183 [ - + ][ # # ]: 1627 : conn_timer_mgr = tag ? new TimerMgr::Tag(*tag) : 0;
184 : :
185 [ - + ][ # # ]: 1627 : if ( conn_timer_mgr )
186 : : {
187 : 0 : ++external_connections;
188 : : // We schedule a timer which removes this connection from memory
189 : : // indefinitively into the future. Ii will expire when the timer
190 : : // mgr is drained but not before.
191 : 0 : ADD_TIMER(&Connection::RemoveConnectionTimer, 1e20, 1,
192 : : TIMER_REMOVE_CONNECTION);
193 : : }
194 : 1627 : }
195 : :
196 : 1627 : Connection::~Connection()
197 : : {
198 [ - + ][ # # ]: 1627 : if ( ! finished )
[ # # ]
199 : 0 : internal_error("Done() not called before destruction of Connection");
200 : :
201 : 1627 : CancelTimers();
202 : :
203 [ + - # # # : 1627 : if ( conn_val )
# ]
204 : : {
205 : 1627 : conn_val->SetOrigin(0);
206 : 1627 : Unref(conn_val);
207 : : }
208 : :
209 [ + + ][ # # ]: 1627 : delete key;
[ # # ]
210 [ + - ][ # # ]: 1627 : delete root_analyzer;
[ # # ]
211 [ - + ][ # # ]: 1627 : delete conn_timer_mgr;
[ # # ]
212 : :
213 : 1627 : --current_connections;
214 [ - + ][ # # ]: 1627 : if ( conn_timer_mgr )
[ # # ]
215 : 0 : --external_connections;
216 [ + - ][ # # ]: 1627 : }
[ # # ]
217 : :
218 : 1627 : void Connection::Done()
219 : : {
220 : 1627 : finished = 1;
221 : :
222 [ + - ][ + - ]: 1627 : if ( root_analyzer && ! root_analyzer->IsFinished() )
[ + - ]
223 : 1627 : root_analyzer->Done();
224 : 1627 : }
225 : :
226 : : void Connection::NextPacket(double t, int is_orig,
227 : : const IP_Hdr* ip, int len, int caplen,
228 : : const u_char*& data,
229 : : int& record_packet, int& record_content,
230 : : // arguments for reproducing packets
231 : : const struct pcap_pkthdr* hdr,
232 : : const u_char* const pkt,
233 : 19690 : int hdr_size)
234 : : {
235 : 19690 : current_hdr = hdr;
236 : 19690 : current_hdr_size = hdr_size;
237 : 19690 : current_timestamp = t;
238 : 19690 : current_pkt = pkt;
239 : :
240 [ - + ]: 19690 : if ( Skipping() )
241 : 0 : return;
242 : :
243 [ + - ]: 19690 : if ( root_analyzer )
244 : : {
245 : 19690 : record_current_packet = record_packet;
246 : 19690 : record_current_content = record_content;
247 : 19690 : root_analyzer->NextPacket(len, data, is_orig, -1, ip, caplen);
248 : 19690 : record_packet = record_current_packet;
249 : 19690 : record_content = record_current_content;
250 : : }
251 : : else
252 : 0 : last_time = t;
253 : :
254 : 19690 : current_hdr = 0;
255 : 19690 : current_hdr_size = 0;
256 : 19690 : current_timestamp = 0;
257 : 19690 : current_pkt = 0;
258 : : }
259 : :
260 : 0 : void Connection::SetLifetime(double lifetime)
261 : : {
262 : 0 : ADD_TIMER(&Connection::DeleteTimer, network_time + lifetime, 0,
263 : : TIMER_CONN_DELETE);
264 : 0 : }
265 : :
266 : 17553 : bool Connection::IsReuse(double t, const u_char* pkt)
267 : : {
268 [ + - ][ + + ]: 17553 : return root_analyzer && root_analyzer->IsReuse(t, pkt);
269 : : }
270 : :
271 : 502 : void Connection::DeleteTimer(double /* t */)
272 : : {
273 [ + - ]: 502 : if ( is_active )
274 : 502 : Event(connection_timeout, 0);
275 : :
276 : 502 : sessions->Remove(this);
277 : 502 : }
278 : :
279 : 1506 : void Connection::InactivityTimer(double t)
280 : : {
281 : : // If the inactivity_timeout is zero, there has been an active
282 : : // timeout once, but it's disabled now. We do nothing then.
283 [ + - ]: 1506 : if ( inactivity_timeout )
284 : : {
285 [ + + ]: 1506 : if ( last_time + inactivity_timeout <= t )
286 : : {
287 : 1074 : Event(connection_timeout, 0);
288 : 1074 : sessions->Remove(this);
289 : 1074 : ++killed_by_inactivity;
290 : : }
291 : : else
292 : 432 : ADD_TIMER(&Connection::InactivityTimer,
293 : : last_time + inactivity_timeout, 0,
294 : : TIMER_CONN_INACTIVITY);
295 : : }
296 : 1506 : }
297 : :
298 : 0 : void Connection::RemoveConnectionTimer(double t)
299 : : {
300 : 0 : Event(connection_state_remove, 0);
301 : 0 : sessions->Remove(this);
302 : 0 : }
303 : :
304 : 1616 : void Connection::SetInactivityTimeout(double timeout)
305 : : {
306 : : // We add a new inactivity timer even if there already is one. When
307 : : // it fires, we always use the current value to check for inactivity.
308 [ + - ]: 1616 : if ( timeout )
309 : 1616 : ADD_TIMER(&Connection::InactivityTimer,
310 : : last_time + timeout, 0, TIMER_CONN_INACTIVITY);
311 : :
312 : 1616 : inactivity_timeout = timeout;
313 : 1616 : }
314 : :
315 : 1722 : void Connection::EnableStatusUpdateTimer()
316 : : {
317 [ - + ][ # # ]: 1722 : if ( connection_status_update && connection_status_update_interval )
[ - + ]
318 : : {
319 : 0 : ADD_TIMER(&Connection::StatusUpdateTimer,
320 : : network_time + connection_status_update_interval, 0,
321 : : TIMER_CONN_STATUS_UPDATE);
322 : 0 : installed_status_timer = 1;
323 : : }
324 : 1722 : }
325 : :
326 : 0 : void Connection::StatusUpdateTimer(double t)
327 : : {
328 : 0 : val_list* vl = new val_list(1);
329 : 0 : vl->append(BuildConnVal());
330 : 0 : ConnectionEvent(connection_status_update, 0, vl);
331 : 0 : ADD_TIMER(&Connection::StatusUpdateTimer,
332 : : network_time + connection_status_update_interval, 0,
333 : : TIMER_CONN_STATUS_UPDATE);
334 : 0 : }
335 : :
336 : 17023 : RecordVal* Connection::BuildConnVal()
337 : : {
338 [ + + ]: 17023 : if ( ! conn_val )
339 : : {
340 : 1627 : conn_val = new RecordVal(connection_type);
341 : :
342 : 1627 : TransportProto prot_type = ConnTransport();
343 : :
344 : 1627 : RecordVal* id_val = new RecordVal(conn_id);
345 : 1627 : id_val->Assign(0, new AddrVal(orig_addr));
346 : 1627 : id_val->Assign(1, new PortVal(ntohs(orig_port), prot_type));
347 : 1627 : id_val->Assign(2, new AddrVal(resp_addr));
348 : 1627 : id_val->Assign(3, new PortVal(ntohs(resp_port), prot_type));
349 : 1627 : conn_val->Assign(0, id_val);
350 : :
351 : 1627 : orig_endp = new RecordVal(endpoint);
352 : 1627 : orig_endp->Assign(0, new Val(0, TYPE_COUNT));
353 : 1627 : orig_endp->Assign(1, new Val(0, TYPE_COUNT));
354 : 1627 : conn_val->Assign(1, orig_endp);
355 : :
356 : 1627 : resp_endp = new RecordVal(endpoint);
357 : 1627 : resp_endp->Assign(0, new Val(0, TYPE_COUNT));
358 : 1627 : resp_endp->Assign(1, new Val(0, TYPE_COUNT));
359 : 1627 : conn_val->Assign(2, resp_endp);
360 : :
361 : : // conn_val->Assign(3, new Val(start_time, TYPE_TIME)); // ###
362 : 1627 : conn_val->Assign(5, new TableVal(string_set)); // service
363 : 1627 : conn_val->Assign(6, new StringVal("")); // addl
364 : 1627 : conn_val->Assign(7, new Val(0, TYPE_COUNT)); // hot
365 : 1627 : conn_val->Assign(8, new StringVal("")); // history
366 : : }
367 : :
368 [ + - ]: 17023 : if ( root_analyzer )
369 : : {
370 : 17023 : root_analyzer->UpdateEndpointVal(orig_endp, 1);
371 : 17023 : root_analyzer->UpdateEndpointVal(resp_endp, 0);
372 : : }
373 : :
374 : 17023 : conn_val->Assign(3, new Val(start_time, TYPE_TIME)); // ###
375 : 17023 : conn_val->Assign(4, new Val(last_time - start_time, TYPE_INTERVAL));
376 : 17023 : conn_val->Assign(8, new StringVal(history.c_str()));
377 : :
378 : 17023 : conn_val->SetOrigin(this);
379 : :
380 : 17023 : Ref(conn_val);
381 : :
382 : 17023 : return conn_val;
383 : : }
384 : :
385 : 0 : Analyzer* Connection::FindAnalyzer(AnalyzerID id)
386 : : {
387 [ # # ]: 0 : return root_analyzer ? root_analyzer->FindChild(id) : 0;
388 : : }
389 : :
390 : 8 : Analyzer* Connection::FindAnalyzer(AnalyzerTag::Tag tag)
391 : : {
392 [ + - ]: 8 : return root_analyzer ? root_analyzer->FindChild(tag) : 0;
393 : : }
394 : :
395 : 0 : void Connection::AppendAddl(const char* str)
396 : : {
397 : 0 : Unref(BuildConnVal());
398 : :
399 : 0 : const char* old = conn_val->Lookup(6)->AsString()->CheckString();
400 [ # # ]: 0 : const char* format = *old ? "%s %s" : "%s%s";
401 : :
402 : 0 : conn_val->Assign(6, new StringVal(fmt(format, old, str)));
403 : 0 : }
404 : :
405 : : // Returns true if the character at s separates a version number.
406 : 0 : static inline bool is_version_sep(const char* s, const char* end)
407 : : {
408 : : return
409 : : // foo-1.2.3
410 : : (s < end - 1 && ispunct(s[0]) && isdigit(s[1])) ||
411 : : // foo-v1.2.3
412 : : (s < end - 2 && ispunct(s[0]) &&
413 : : tolower(s[1]) == 'v' && isdigit(s[2])) ||
414 : : // foo 1.2.3
415 [ # # ][ # # ]: 0 : isspace(s[0]);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
416 : : }
417 : :
418 : 26764 : void Connection::Match(Rule::PatternType type, const u_char* data, int len, bool is_orig, bool bol, bool eol, bool clear_state)
419 : : {
420 [ + - ]: 26764 : if ( primary_PIA )
421 : 26764 : primary_PIA->Match(type, data, len, is_orig, bol, eol, clear_state);
422 : 26764 : }
423 : :
424 : 0 : Val* Connection::BuildVersionVal(const char* s, int len)
425 : : {
426 : 0 : Val* name = 0;
427 : 0 : Val* major = 0;
428 : 0 : Val* minor = 0;
429 : 0 : Val* minor2 = 0;
430 : 0 : Val* addl = 0;
431 : :
432 : 0 : const char* last = s + len;
433 : 0 : const char* e = s;
434 : :
435 : : // This is all just a guess...
436 : :
437 : : // Eat non-alpha-numerical chars.
438 [ # # ][ # # ]: 0 : for ( ; s < last && ! isalnum(*s); ++s )
439 : : ;
440 : :
441 : : // Leading characters are the program name.
442 : : // (first character must not be a digit)
443 [ # # ]: 0 : if ( isalpha(*s) )
444 : : {
445 [ # # ][ # # ]: 0 : for ( e = s; e < last && ! is_version_sep(e, last); ++e )
[ # # ]
446 : : ;
447 : :
448 [ # # ]: 0 : if ( s != e )
449 : 0 : name = new StringVal(e - s, s);
450 : : }
451 : :
452 : : // Find first number - that's the major version.
453 [ # # ][ # # ]: 0 : for ( s = e; s < last && ! isdigit(*s); ++s )
454 : : ;
455 [ # # ][ # # ]: 0 : for ( e = s; e < last && isdigit(*e); ++e )
456 : : ;
457 : :
458 [ # # ]: 0 : if ( s != e )
459 : 0 : major = new Val(atoi(s), TYPE_INT);
460 : :
461 : : // Find second number seperated only by punctuation chars -
462 : : // that's the minor version.
463 [ # # ][ # # ]: 0 : for ( s = e; s < last && ispunct(*s); ++s )
464 : : ;
465 [ # # ][ # # ]: 0 : for ( e = s; e < last && isdigit(*e); ++e )
466 : : ;
467 : :
468 [ # # ]: 0 : if ( s != e )
469 : 0 : minor = new Val(atoi(s), TYPE_INT);
470 : :
471 : : // Find second number seperated only by punctuation chars; -
472 : : // that's the minor version.
473 [ # # ][ # # ]: 0 : for ( s = e; s < last && ispunct(*s); ++s )
474 : : ;
475 [ # # ][ # # ]: 0 : for ( e = s; e < last && isdigit(*e); ++e )
476 : : ;
477 : :
478 [ # # ]: 0 : if ( s != e )
479 : 0 : minor2 = new Val(atoi(s), TYPE_INT);
480 : :
481 : : // Anything after following punctuation and until next white space is
482 : : // an additional version string.
483 [ # # ][ # # ]: 0 : for ( s = e; s < last && ispunct(*s); ++s )
484 : : ;
485 [ # # ][ # # ]: 0 : for ( e = s; e < last && ! isspace(*e); ++e )
486 : : ;
487 : :
488 [ # # ]: 0 : if ( s != e )
489 : 0 : addl = new StringVal(e - s, s);
490 : :
491 : : // If we do not have a name yet, the next alphanumerical string is it.
492 [ # # ]: 0 : if ( ! name )
493 : : { // eat non-alpha-numerical characters
494 [ # # ][ # # ]: 0 : for ( s = e; s < last && ! isalpha(*s); ++s )
495 : : ;
496 : :
497 : : // Get name.
498 [ # # ][ # # ]: 0 : for ( e = s; e < last && (isalnum(*e) || *e == '_'); ++e )
[ # # ]
499 : : ;
500 : :
501 [ # # ]: 0 : if ( s != e )
502 : 0 : name = new StringVal(e - s, s);
503 : : }
504 : :
505 : : // We need at least a name.
506 [ # # ]: 0 : if ( ! name )
507 : 0 : return 0;
508 : :
509 : 0 : RecordVal* version = new RecordVal(software_version);
510 [ # # ]: 0 : version->Assign(0, major ? major : new Val(-1, TYPE_INT));
511 [ # # ]: 0 : version->Assign(1, minor ? minor : new Val(-1, TYPE_INT));
512 [ # # ]: 0 : version->Assign(2, minor2 ? minor2 : new Val(-1, TYPE_INT));
513 [ # # ]: 0 : version->Assign(3, addl ? addl : new StringVal(""));
514 : :
515 : 0 : RecordVal* sw = new RecordVal(software);
516 : 0 : sw->Assign(0, name);
517 : 0 : sw->Assign(1, version);
518 : :
519 : 0 : return sw;
520 : : }
521 : :
522 : : int Connection::VersionFoundEvent(const uint32* addr, const char* s, int len,
523 : 0 : Analyzer* analyzer)
524 : : {
525 [ # # ][ # # ]: 0 : if ( ! software_version_found && ! software_parse_error )
[ # # ]
526 : 0 : return 1;
527 : :
528 [ # # ]: 0 : if ( ! is_printable(s, len) )
529 : 0 : return 0;
530 : :
531 : 0 : Val* val = BuildVersionVal(s, len);
532 [ # # ]: 0 : if ( ! val )
533 : : {
534 [ # # ]: 0 : if ( software_parse_error )
535 : : {
536 : 0 : val_list* vl = new val_list;
537 : 0 : vl->append(BuildConnVal());
538 : 0 : vl->append(new AddrVal(addr));
539 : 0 : vl->append(new StringVal(len, s));
540 : 0 : ConnectionEvent(software_parse_error, analyzer, vl);
541 : : }
542 : 0 : return 0;
543 : : }
544 : :
545 [ # # ]: 0 : if ( software_version_found )
546 : : {
547 : 0 : val_list* vl = new val_list;
548 : 0 : vl->append(BuildConnVal());
549 : 0 : vl->append(new AddrVal(addr));
550 : 0 : vl->append(val);
551 : 0 : vl->append(new StringVal(len, s));
552 : 0 : ConnectionEvent(software_version_found, 0, vl);
553 : : }
554 : : else
555 : 0 : Unref(val);
556 : :
557 : 0 : return 1;
558 : : }
559 : :
560 : : int Connection::UnparsedVersionFoundEvent(const uint32* addr,
561 : 0 : const char* full, int len, Analyzer* analyzer)
562 : : {
563 : : // Skip leading white space.
564 [ # # ][ # # ]: 0 : while ( len && isspace(*full) )
565 : : {
566 : 0 : --len;
567 : 0 : ++full;
568 : : }
569 : :
570 [ # # ]: 0 : if ( ! is_printable(full, len) )
571 : 0 : return 0;
572 : :
573 [ # # ]: 0 : if ( software_unparsed_version_found )
574 : : {
575 : 0 : val_list* vl = new val_list;
576 : 0 : vl->append(BuildConnVal());
577 : 0 : vl->append(new AddrVal(addr));
578 : 0 : vl->append(new StringVal(len, full));
579 : 0 : ConnectionEvent(software_unparsed_version_found, analyzer, vl);
580 : : }
581 : :
582 : 0 : return 1;
583 : : }
584 : :
585 : 8713 : void Connection::Event(EventHandlerPtr f, Analyzer* analyzer, const char* name)
586 : : {
587 [ + + ]: 8713 : if ( ! f )
588 : 3728 : return;
589 : :
590 : 4985 : val_list* vl = new val_list(2);
591 [ + + ]: 4985 : if ( name )
592 : 433 : vl->append(new StringVal(name));
593 : 4985 : vl->append(BuildConnVal());
594 : :
595 : 8713 : ConnectionEvent(f, analyzer, vl);
596 : : }
597 : :
598 : 0 : void Connection::Event(EventHandlerPtr f, Analyzer* analyzer, Val* v1, Val* v2)
599 : : {
600 [ # # ]: 0 : if ( ! f )
601 : : {
602 : 0 : Unref(v1);
603 : 0 : Unref(v2);
604 : 0 : return;
605 : : }
606 : :
607 : 0 : val_list* vl = new val_list(3);
608 : 0 : vl->append(BuildConnVal());
609 : 0 : vl->append(v1);
610 : :
611 [ # # ]: 0 : if ( v2 )
612 : 0 : vl->append(v2);
613 : :
614 : 0 : ConnectionEvent(f, analyzer, vl);
615 : : }
616 : :
617 : 16749 : void Connection::ConnectionEvent(EventHandlerPtr f, Analyzer* a, val_list* vl)
618 : : {
619 [ - + ]: 16749 : if ( ! f )
620 : : {
621 : : // This may actually happen if there is no local handler
622 : : // and a previously existing remote handler went away.
623 [ # # ]: 0 : loop_over_list(*vl, i)
624 : 0 : Unref((*vl)[i]);
625 [ # # ]: 0 : delete vl;
626 : 0 : return;
627 : : }
628 : :
629 : : // "this" is passed as a cookie for the event
630 : : mgr.QueueEvent(f, vl, SOURCE_LOCAL,
631 [ + + ]: 16749 : a ? a->GetID() : 0, GetTimerMgr(), this);
632 : : }
633 : :
634 : 433 : void Connection::Weird(const char* name)
635 : : {
636 : 433 : weird = 1;
637 [ + - ]: 433 : if ( conn_weird )
638 : 433 : Event(conn_weird, 0, name);
639 : : else
640 : 0 : fprintf(stderr, "%.06f weird: %s\n", network_time, name);
641 : 433 : }
642 : :
643 : 0 : void Connection::Weird(const char* name, const char* addl)
644 : : {
645 : 0 : weird = 1;
646 [ # # ]: 0 : if ( conn_weird_addl )
647 : : {
648 : 0 : val_list* vl = new val_list(3);
649 : :
650 : 0 : vl->append(new StringVal(name));
651 : 0 : vl->append(BuildConnVal());
652 : 0 : vl->append(new StringVal(addl));
653 : :
654 : 0 : ConnectionEvent(conn_weird_addl, 0, vl);
655 : : }
656 : :
657 : : else
658 : 0 : fprintf(stderr, "%.06f weird: %s (%s)\n", network_time, name, addl);
659 : 0 : }
660 : :
661 : 0 : void Connection::Weird(const char* name, int addl_len, const char* addl)
662 : : {
663 : 0 : weird = 1;
664 [ # # ]: 0 : if ( conn_weird_addl )
665 : : {
666 : 0 : val_list* vl = new val_list(3);
667 : :
668 : 0 : vl->append(new StringVal(name));
669 : 0 : vl->append(BuildConnVal());
670 : 0 : vl->append(new StringVal(addl_len, addl));
671 : :
672 : 0 : ConnectionEvent(conn_weird_addl, 0, vl);
673 : : }
674 : :
675 : : else
676 : : {
677 : 0 : fprintf(stderr, "%.06f weird: %s (", network_time, name);
678 [ # # ]: 0 : for ( int i = 0; i < addl_len; ++i )
679 : 0 : fputc(addl[i], stderr);
680 : 0 : fprintf(stderr, ")\n");
681 : : }
682 : 0 : }
683 : :
684 : : void Connection::AddTimer(timer_func timer, double t, int do_expire,
685 : 2048 : TimerType type)
686 : : {
687 [ + - ]: 2048 : if ( timers_canceled )
688 : 2048 : return;
689 : :
690 : : // If the key is cleared, the connection isn't stored in the connection
691 : : // table anymore and will soon be deleted. We're not installing new
692 : : // timers anymore then.
693 [ - + ]: 2048 : if ( ! key )
694 : 0 : return;
695 : :
696 : 2048 : Timer* conn_timer = new ConnectionTimer(this, timer, t, do_expire, type);
697 : 2048 : GetTimerMgr()->Add(conn_timer);
698 : 2048 : timers.append(conn_timer);
699 : : }
700 : :
701 : 3554 : void Connection::RemoveTimer(Timer* t)
702 : : {
703 : 3554 : timers.remove(t);
704 : 3554 : }
705 : :
706 : 3251 : void Connection::CancelTimers()
707 : : {
708 : : // We are going to cancel our timers which, in turn, may cause them to
709 : : // call RemoveTimer(), which would then modify the list we're just
710 : : // traversing. Thus, we first make a copy of the list which we then
711 : : // iterate through.
712 : 3251 : timer_list tmp(timers.length());
713 [ + + ]: 3790 : loop_over_list(timers, j)
714 : 539 : tmp.append(timers[j]);
715 : :
716 [ + + ]: 3790 : loop_over_list(tmp, i)
717 : 539 : GetTimerMgr()->Cancel(tmp[i]);
718 : :
719 : 3251 : timers_canceled = 1;
720 : 3251 : timers.clear();
721 : 3251 : }
722 : :
723 : 40026 : TimerMgr* Connection::GetTimerMgr() const
724 : : {
725 [ + - ]: 40026 : if ( ! conn_timer_mgr )
726 : : // Global manager.
727 : 40026 : return timer_mgr;
728 : :
729 : : // We need to check whether the local timer manager still exists;
730 : : // it may have already been timed out, in which case we fall back
731 : : // to the global manager (though this should be rare).
732 : 0 : TimerMgr* local_mgr = sessions->LookupTimerMgr(conn_timer_mgr, false);
733 [ # # ]: 40026 : return local_mgr ? local_mgr : timer_mgr;
734 : : }
735 : :
736 : 0 : void Connection::FlipRoles()
737 : : {
738 : : uint32 tmp_addr[NUM_ADDR_WORDS];
739 : 0 : copy_addr(resp_addr, tmp_addr);
740 : 0 : copy_addr(orig_addr, resp_addr);
741 : 0 : copy_addr(tmp_addr, orig_addr);
742 : :
743 : 0 : uint32 tmp_port = resp_port;
744 : 0 : resp_port = orig_port;
745 : 0 : orig_port = tmp_port;
746 : :
747 : 0 : RecordVal* tmp_rc = resp_endp;
748 : 0 : resp_endp = orig_endp;
749 : 0 : orig_endp = tmp_rc;
750 : :
751 : 0 : Unref(conn_val);
752 : 0 : conn_val = 0;
753 : :
754 [ # # ]: 0 : if ( root_analyzer )
755 : 0 : root_analyzer->FlipRoles();
756 : 0 : }
757 : :
758 : 19166 : int Connection::RewritingTrace()
759 : : {
760 [ + - ]: 19166 : return root_analyzer ? root_analyzer->RewritingTrace() : 0;
761 : : }
762 : :
763 : 567 : Rewriter* Connection::TraceRewriter() const
764 : : {
765 [ + - ]: 567 : return root_analyzer ? root_analyzer->TraceRewriter() : 0;
766 : : }
767 : :
768 : 0 : unsigned int Connection::MemoryAllocation() const
769 : : {
770 : : return padded_sizeof(*this)
771 : : + (key ? key->MemoryAllocation() : 0)
772 : : + (timers.MemoryAllocation() - padded_sizeof(timers))
773 : : + (conn_val ? conn_val->MemoryAllocation() : 0)
774 [ # # ][ # # ]: 0 : + (root_analyzer ? root_analyzer->MemoryAllocation(): 0)
[ # # ]
775 : : // login_conn is just a casted 'this'.
776 : : // primary_PIA is already contained in the analyzer tree.
777 : : ;
778 : : }
779 : :
780 : 0 : unsigned int Connection::MemoryAllocationConnVal() const
781 : : {
782 [ # # ]: 0 : return conn_val ? conn_val->MemoryAllocation() : 0;
783 : : }
784 : :
785 : 0 : void Connection::Describe(ODesc* d) const
786 : : {
787 : 0 : d->Add(start_time);
788 : 0 : d->Add("(");
789 : 0 : d->Add(last_time);
790 : 0 : d->AddSP(")");
791 : :
792 [ # # # # : 0 : switch ( proto ) {
# ]
793 : : case TRANSPORT_TCP:
794 : 0 : d->Add("TCP");
795 : 0 : break;
796 : :
797 : : case TRANSPORT_UDP:
798 : 0 : d->Add("UDP");
799 : 0 : break;
800 : :
801 : : case TRANSPORT_ICMP:
802 : 0 : d->Add("ICMP");
803 : 0 : break;
804 : :
805 : : case TRANSPORT_UNKNOWN:
806 : 0 : internal_error("unknown transport in Connction::Describe()");
807 : : break;
808 : : }
809 : :
810 : 0 : d->SP();
811 : 0 : d->Add(dotted_addr(orig_addr));
812 : 0 : d->Add(":");
813 : 0 : d->Add(ntohs(orig_port));
814 : :
815 : 0 : d->SP();
816 : 0 : d->AddSP("->");
817 : :
818 : 0 : d->Add(dotted_addr(resp_addr));
819 : 0 : d->Add(":");
820 : 0 : d->Add(ntohs(resp_port));
821 : :
822 : 0 : d->NL();
823 : 0 : }
824 : :
825 : 0 : bool Connection::Serialize(SerialInfo* info) const
826 : : {
827 : 0 : return SerialObj::Serialize(info);
828 : : }
829 : :
830 : 0 : Connection* Connection::Unserialize(UnserialInfo* info)
831 : : {
832 : 0 : return (Connection*) SerialObj::Unserialize(info, SER_CONNECTION);
833 : : }
834 : :
835 : 0 : bool Connection::DoSerialize(SerialInfo* info) const
836 : : {
837 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_CONNECTION, BroObj);
838 : :
839 : : // First we write the members which are needed to
840 : : // create the HashKey.
841 [ # # ]: 0 : for ( int j = 0; j < NUM_ADDR_WORDS; ++j )
842 [ # # ][ # # ]: 0 : if ( ! SERIALIZE(orig_addr[j]) || ! SERIALIZE(resp_addr[j]) )
[ # # ]
843 : 0 : return false;
844 : :
845 [ # # ][ # # ]: 0 : if ( ! SERIALIZE(orig_port) || ! SERIALIZE(resp_port) )
[ # # ]
846 : 0 : return false;
847 : :
848 [ # # ]: 0 : if ( ! SERIALIZE(timers.length()) )
849 : 0 : return false;
850 : :
851 [ # # ]: 0 : loop_over_list(timers, i)
852 [ # # ]: 0 : if ( ! timers[i]->Serialize(info) )
853 : 0 : return false;
854 : :
855 [ # # ][ # # ]: 0 : SERIALIZE_OPTIONAL(conn_val);
[ # # ][ # # ]
[ # # ][ # # ]
856 [ # # ][ # # ]: 0 : SERIALIZE_OPTIONAL(orig_endp);
[ # # ][ # # ]
[ # # ][ # # ]
857 [ # # ][ # # ]: 0 : SERIALIZE_OPTIONAL(resp_endp);
[ # # ][ # # ]
[ # # ][ # # ]
858 : :
859 : : // FIXME: RuleEndpointState not yet serializable.
860 : : // FIXME: Analyzers not yet serializable.
861 : :
862 : : return
863 : : SERIALIZE(int(proto)) &&
864 : : SERIALIZE(history) &&
865 : : SERIALIZE(hist_seen) &&
866 : : SERIALIZE(start_time) &&
867 : : SERIALIZE(last_time) &&
868 : : SERIALIZE(inactivity_timeout) &&
869 : : SERIALIZE(suppress_event) &&
870 : : SERIALIZE(login_conn != 0) &&
871 : : SERIALIZE_BIT(installed_status_timer) &&
872 : : SERIALIZE_BIT(timers_canceled) &&
873 : : SERIALIZE_BIT(is_active) &&
874 : : SERIALIZE_BIT(skip) &&
875 : : SERIALIZE_BIT(weird) &&
876 : : SERIALIZE_BIT(finished) &&
877 : : SERIALIZE_BIT(record_packets) &&
878 : : SERIALIZE_BIT(record_contents) &&
879 [ # # ][ # # ]: 0 : SERIALIZE_BIT(persistent);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
880 : : }
881 : :
882 : 0 : bool Connection::DoUnserialize(UnserialInfo* info)
883 : : {
884 : : // Make sure this is initialized for the condition in Unserialize().
885 : 0 : persistent = 0;
886 : :
887 [ # # ]: 0 : DO_UNSERIALIZE(BroObj);
888 : :
889 : : // Build the hash key first. Some of the recursive *::Unserialize()
890 : : // functions may need it.
891 [ # # ]: 0 : for ( int i = 0; i < NUM_ADDR_WORDS; ++i )
892 [ # # ][ # # ]: 0 : if ( ! UNSERIALIZE(&orig_addr[i]) || ! UNSERIALIZE(&resp_addr[i]) )
[ # # ]
893 : 0 : goto error;
894 : :
895 [ # # ][ # # ]: 0 : if ( ! UNSERIALIZE(&orig_port) || ! UNSERIALIZE(&resp_port) )
[ # # ]
896 : 0 : goto error;
897 : :
898 : : ConnID id;
899 : 0 : id.src_addr = orig_addr;
900 : 0 : id.dst_addr = resp_addr;
901 : : // This doesn't work for ICMP. But I guess this is not really important.
902 : 0 : id.src_port = orig_port;
903 : 0 : id.dst_port = resp_port;
904 : 0 : id.is_one_way = 0; // ### incorrect for ICMP
905 : 0 : key = id.BuildConnKey();
906 : :
907 : : int len;
908 [ # # ]: 0 : if ( ! UNSERIALIZE(&len) )
909 : 0 : goto error;
910 : :
911 [ # # ]: 0 : while ( len-- )
912 : : {
913 : 0 : Timer* t = Timer::Unserialize(info);
914 [ # # ]: 0 : if ( ! t )
915 : 0 : goto error;
916 : 0 : timers.append(t);
917 : : }
918 : :
919 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(conn_val,
[ # # ]
920 : : (RecordVal*) Val::Unserialize(info, connection_type));
921 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(orig_endp,
[ # # ]
922 : : (RecordVal*) Val::Unserialize(info, endpoint));
923 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(resp_endp,
[ # # ]
924 : : (RecordVal*) Val::Unserialize(info, endpoint));
925 : :
926 : : int iproto;
927 : :
928 [ # # ][ # # ]: 0 : if ( ! (UNSERIALIZE(&iproto) &&
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
929 : : UNSERIALIZE(&history) &&
930 : : UNSERIALIZE(&hist_seen) &&
931 : : UNSERIALIZE(&start_time) &&
932 : : UNSERIALIZE(&last_time) &&
933 : : UNSERIALIZE(&inactivity_timeout) &&
934 : : UNSERIALIZE(&suppress_event)) )
935 : 0 : goto error;
936 : :
937 : 0 : proto = static_cast<TransportProto>(iproto);
938 : :
939 : : bool has_login_conn;
940 [ # # ]: 0 : if ( ! UNSERIALIZE(&has_login_conn) )
941 : 0 : goto error;
942 : :
943 [ # # ]: 0 : login_conn = has_login_conn ? (LoginConn*) this : 0;
944 : :
945 [ # # ]: 0 : UNSERIALIZE_BIT(installed_status_timer);
946 [ # # ]: 0 : UNSERIALIZE_BIT(timers_canceled);
947 [ # # ]: 0 : UNSERIALIZE_BIT(is_active);
948 [ # # ]: 0 : UNSERIALIZE_BIT(skip);
949 [ # # ]: 0 : UNSERIALIZE_BIT(weird);
950 [ # # ]: 0 : UNSERIALIZE_BIT(finished);
951 [ # # ]: 0 : UNSERIALIZE_BIT(record_packets);
952 [ # # ]: 0 : UNSERIALIZE_BIT(record_contents);
953 [ # # ]: 0 : UNSERIALIZE_BIT(persistent);
954 : :
955 : : // Hmm... Why does each connection store a sessions ptr?
956 : 0 : sessions = ::sessions;
957 : :
958 : 0 : root_analyzer = 0;
959 : 0 : primary_PIA = 0;
960 : 0 : conn_timer_mgr = 0;
961 : :
962 : 0 : return true;
963 : :
964 : 0 : error:
965 : 0 : abort();
966 : : CancelTimers();
967 : 0 : return false;
968 : : }
969 : :
970 : 1627 : void Connection::SetRootAnalyzer(TransportLayerAnalyzer* analyzer, PIA* pia)
971 : : {
972 : 1627 : root_analyzer = analyzer;
973 : 1627 : primary_PIA = pia;
974 [ + - ][ + - ]: 1633 : }
|