Branch data Line data Source code
1 : : // $Id: RPC.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 <stdlib.h>
8 : :
9 : : #include "NetVar.h"
10 : : #include "XDR.h"
11 : : #include "RPC.h"
12 : : #include "Sessions.h"
13 : :
14 : : namespace { // local namespace
15 : : const bool DEBUG_rpc_resync = false;
16 : : }
17 : :
18 : : #define MAX_RPC_LEN 65536
19 : :
20 : : // The following correspond to the different RPC status values defined
21 : : // in bro.init.
22 : : // #define BRO_RPC_TIMEOUT 6
23 : : // #define BRO_RPC_AUTH_ERROR 7
24 : : // #define BRO_RPC_UNKNOWN_ERROR 8
25 : :
26 : 0 : RPC_CallInfo::RPC_CallInfo(uint32 arg_xid, const u_char*& buf, int& n)
27 : : {
28 : 0 : xid = arg_xid;
29 : :
30 : 0 : start_time = network_time;
31 : 0 : call_n = n;
32 : 0 : call_buf = new u_char[call_n];
33 : 0 : memcpy((void*) call_buf, (const void*) buf, call_n);
34 : :
35 : 0 : rpc_version = extract_XDR_uint32(buf, n);
36 : 0 : prog = extract_XDR_uint32(buf, n);
37 : 0 : vers = extract_XDR_uint32(buf, n);
38 : 0 : proc = extract_XDR_uint32(buf, n);
39 : 0 : cred_flavor = skip_XDR_opaque_auth(buf, n);
40 : 0 : verf_flavor = skip_XDR_opaque_auth(buf, n);
41 : :
42 : 0 : header_len = call_n - n;
43 : :
44 : 0 : valid_call = false;
45 : :
46 : 0 : v = 0;
47 : 0 : }
48 : :
49 : 0 : RPC_CallInfo::~RPC_CallInfo()
50 : : {
51 [ # # ][ # # ]: 0 : delete [] call_buf;
52 : 0 : Unref(v);
53 : 0 : }
54 : :
55 : 0 : int RPC_CallInfo::CompareRexmit(const u_char* buf, int n) const
56 : : {
57 [ # # ]: 0 : if ( n != call_n )
58 : 0 : return 0;
59 : :
60 : 0 : return memcmp((const void*) call_buf, (const void*) buf, call_n) == 0;
61 : : }
62 : :
63 : :
64 : 0 : void rpc_callinfo_delete_func(void* v)
65 : : {
66 [ # # ]: 0 : delete (RPC_CallInfo*) v;
67 : 0 : }
68 : :
69 : 0 : RPC_Interpreter::RPC_Interpreter(Analyzer* arg_analyzer)
70 : : {
71 : 0 : analyzer = arg_analyzer;
72 : 0 : calls.SetDeleteFunc(rpc_callinfo_delete_func);
73 : 0 : }
74 : :
75 : 0 : RPC_Interpreter::~RPC_Interpreter()
76 : : {
77 [ # # ][ # # ]: 0 : }
[ # # ]
78 : :
79 : 0 : int RPC_Interpreter::DeliverRPC(const u_char* buf, int n, int is_orig)
80 : : {
81 : 0 : uint32 xid = extract_XDR_uint32(buf, n);
82 : 0 : uint32 msg_type = extract_XDR_uint32(buf, n);
83 : :
84 [ # # ]: 0 : if ( ! buf )
85 : 0 : return 0;
86 : :
87 : 0 : HashKey h(&xid, 1);
88 : 0 : RPC_CallInfo* call = calls.Lookup(&h);
89 : :
90 [ # # ]: 0 : if ( msg_type == RPC_CALL )
91 : : {
92 [ # # ]: 0 : if ( ! is_orig )
93 : 0 : Weird("responder_RPC_call");
94 : :
95 [ # # ]: 0 : if ( call )
96 : : {
97 [ # # ]: 0 : if ( ! call->CompareRexmit(buf, n) )
98 : 0 : Weird("RPC_rexmit_inconsistency");
99 : :
100 [ # # ]: 0 : if ( call->HeaderLen() > n )
101 : : {
102 : 0 : Weird("RPC_underflow");
103 : 0 : return 0;
104 : : }
105 : :
106 : 0 : n -= call->HeaderLen();
107 : 0 : buf += call->HeaderLen();
108 : : }
109 : :
110 : : else
111 : : {
112 : 0 : call = new RPC_CallInfo(xid, buf, n);
113 [ # # ]: 0 : if ( ! buf )
114 : : {
115 [ # # ]: 0 : delete call;
116 : 0 : return 0;
117 : : }
118 : :
119 : 0 : calls.Insert(&h, call);
120 : : }
121 : :
122 [ # # ]: 0 : if ( RPC_BuildCall(call, buf, n) )
123 : 0 : call->SetValidCall();
124 : : else
125 : : {
126 : 0 : Weird("bad_RPC");
127 : 0 : return 0;
128 : : }
129 : : }
130 : :
131 [ # # ]: 0 : else if ( msg_type == RPC_REPLY )
132 : : {
133 [ # # ]: 0 : if ( is_orig )
134 : 0 : Weird("originator_RPC_reply");
135 : :
136 : 0 : uint32 reply_stat = extract_XDR_uint32(buf, n);
137 [ # # ]: 0 : if ( ! buf )
138 : 0 : return 0;
139 : :
140 : 0 : uint32 status = BroEnum::RPC_UNKNOWN_ERROR;
141 : :
142 [ # # ]: 0 : if ( reply_stat == RPC_MSG_ACCEPTED )
143 : : {
144 : 0 : (void) skip_XDR_opaque_auth(buf, n);
145 : 0 : uint32 accept_stat = extract_XDR_uint32(buf, n);
146 : :
147 : : // The first members of BroEnum::RPC_* correspond
148 : : // to accept_stat.
149 [ # # ]: 0 : if ( accept_stat <= RPC_SYSTEM_ERR )
150 : 0 : status = accept_stat;
151 : :
152 [ # # ]: 0 : if ( ! buf )
153 : 0 : return 0;
154 : :
155 [ # # ]: 0 : if ( accept_stat == RPC_PROG_MISMATCH )
156 : : {
157 : 0 : (void) extract_XDR_uint32(buf, n);
158 : 0 : (void) extract_XDR_uint32(buf, n);
159 : :
160 [ # # ]: 0 : if ( ! buf )
161 : 0 : return 0;
162 : : }
163 : : }
164 : :
165 [ # # ]: 0 : else if ( reply_stat == RPC_MSG_DENIED )
166 : : {
167 : 0 : uint32 reject_stat = extract_XDR_uint32(buf, n);
168 [ # # ]: 0 : if ( ! buf )
169 : 0 : return 0;
170 : :
171 [ # # ]: 0 : if ( reject_stat == RPC_MISMATCH )
172 : : {
173 : : // Note that RPC_MISMATCH == 0 == RPC_SUCCESS.
174 : 0 : status = BroEnum::RPC_VERS_MISMATCH;
175 : :
176 : 0 : (void) extract_XDR_uint32(buf, n);
177 : 0 : (void) extract_XDR_uint32(buf, n);
178 : :
179 [ # # ]: 0 : if ( ! buf )
180 : 0 : return 0;
181 : : }
182 : :
183 [ # # ]: 0 : else if ( reject_stat == RPC_AUTH_ERROR )
184 : : {
185 : 0 : status = BroEnum::RPC_AUTH_ERROR;
186 : :
187 : 0 : (void) extract_XDR_uint32(buf, n);
188 [ # # ]: 0 : if ( ! buf )
189 : 0 : return 0;
190 : : }
191 : :
192 : : else
193 : : {
194 : 0 : status = BroEnum::RPC_UNKNOWN_ERROR;
195 : 0 : Weird("bad_RPC");
196 : : }
197 : : }
198 : :
199 : : else
200 : 0 : Weird("bad_RPC");
201 : :
202 [ # # ]: 0 : if ( call )
203 : : {
204 : 0 : int success = status == RPC_SUCCESS;
205 : :
206 [ # # ]: 0 : if ( ! call->IsValidCall() )
207 : : {
208 [ # # ]: 0 : if ( success )
209 : 0 : Weird("successful_RPC_reply_to_invalid_request");
210 : : // We can't process this further, even if
211 : : // it was successful, because the call
212 : : // info won't be fully set up.
213 : : }
214 : :
215 : : else
216 : : {
217 : 0 : EventHandlerPtr event;
218 : : Val* reply;
219 [ # # ]: 0 : if ( ! RPC_BuildReply(call, success, buf,
220 : : n, event, reply) )
221 : 0 : Weird("bad_RPC");
222 : : else
223 : : {
224 : : Event(event, call->TakeRequestVal(),
225 : 0 : status, reply);
226 : : }
227 : : }
228 : :
229 : 0 : RPC_Event(call, status, n);
230 : :
231 [ # # ]: 0 : delete calls.RemoveEntry(&h);
232 : : }
233 : : else
234 : : {
235 : 0 : Weird("unpaired_RPC_response");
236 : 0 : n = 0;
237 : : }
238 : : }
239 : :
240 : : else
241 : 0 : Weird("bad_RPC");
242 : :
243 [ # # ]: 0 : if ( n > 0 )
244 : : {
245 : : // If it's just padded with zeroes, don't complain.
246 [ # # ]: 0 : for ( ; n > 0; --n, ++buf )
247 [ # # ]: 0 : if ( *buf != 0 )
248 : 0 : break;
249 : :
250 [ # # ]: 0 : if ( n > 0 )
251 : 0 : Weird("excess_RPC");
252 : : }
253 : :
254 [ # # ]: 0 : else if ( n < 0 )
255 : 0 : internal_error("RPC underflow");
256 : :
257 : 0 : return 1;
258 : : }
259 : :
260 : 0 : void RPC_Interpreter::Timeout()
261 : : {
262 : 0 : IterCookie* cookie = calls.InitForIteration();
263 : : RPC_CallInfo* c;
264 : :
265 [ # # ]: 0 : while ( (c = calls.NextEntry(cookie)) )
266 : : {
267 : 0 : RPC_Event(c, BroEnum::RPC_TIMEOUT, 0);
268 [ # # ]: 0 : if ( c->IsValidCall() )
269 : : {
270 : : const u_char* buf;
271 : 0 : int n = 0;
272 : 0 : EventHandlerPtr event;
273 : : Val* reply;
274 [ # # ]: 0 : if ( ! RPC_BuildReply(c, 0, buf, n, event, reply) )
275 : 0 : Weird("bad_RPC");
276 : : else
277 : : {
278 : : Event(event, c->TakeRequestVal(),
279 : 0 : BroEnum::RPC_TIMEOUT, reply);
280 : : }
281 : : }
282 : : }
283 : 0 : }
284 : :
285 : 0 : void RPC_Interpreter::RPC_Event(RPC_CallInfo* c, int status, int reply_len)
286 : : {
287 [ # # ]: 0 : if ( rpc_call )
288 : : {
289 : 0 : val_list* vl = new val_list;
290 : 0 : vl->append(analyzer->BuildConnVal());
291 : 0 : vl->append(new Val(c->Program(), TYPE_COUNT));
292 : 0 : vl->append(new Val(c->Version(), TYPE_COUNT));
293 : 0 : vl->append(new Val(c->Proc(), TYPE_COUNT));
294 : 0 : vl->append(new Val(status, TYPE_COUNT));
295 : 0 : vl->append(new Val(c->StartTime(), TYPE_TIME));
296 : 0 : vl->append(new Val(c->CallLen(), TYPE_COUNT));
297 : 0 : vl->append(new Val(reply_len, TYPE_COUNT));
298 : 0 : analyzer->ConnectionEvent(rpc_call, vl);
299 : : }
300 : 0 : }
301 : :
302 : 0 : void RPC_Interpreter::Weird(const char* msg)
303 : : {
304 : 0 : analyzer->Weird(msg);
305 : 0 : }
306 : :
307 : :
308 : : Contents_RPC::Contents_RPC(Connection* conn, bool orig,
309 : 0 : RPC_Interpreter* arg_interp)
310 : 0 : : TCP_SupportAnalyzer(AnalyzerTag::Contents_RPC, conn, orig)
311 : : {
312 : 0 : interp = arg_interp;
313 : 0 : resync = false;
314 : 0 : msg_buf = 0;
315 : 0 : InitBuffer();
316 : 0 : }
317 : :
318 : 0 : void Contents_RPC::Init()
319 : : {
320 : 0 : TCP_SupportAnalyzer::Init();
321 : :
322 : : TCP_Analyzer* tcp =
323 : 0 : static_cast<TCP_ApplicationAnalyzer*>(Parent())->TCP();
324 [ # # ]: 0 : assert(tcp);
325 : :
326 : : resync = (IsOrig() ? tcp->OrigState() : tcp->RespState()) !=
327 [ # # ]: 0 : TCP_ENDPOINT_ESTABLISHED;
328 : 0 : }
329 : :
330 : 0 : void Contents_RPC::InitBuffer()
331 : : {
332 : 0 : buf_len = 4;
333 : :
334 : : // For record marker:
335 [ # # ]: 0 : delete [] msg_buf;
336 : 0 : msg_buf = new u_char[buf_len];
337 : :
338 : 0 : buf_n = 0;
339 : 0 : last_frag = 0;
340 : 0 : state = RPC_RECORD_MARKER;
341 : 0 : }
342 : :
343 : 0 : Contents_RPC::~Contents_RPC()
344 : : {
345 [ # # ][ # # ]: 0 : delete [] msg_buf;
[ # # ]
346 [ # # ][ # # ]: 0 : }
[ # # ]
347 : :
348 : 0 : void Contents_RPC::Undelivered(int seq, int len, bool orig)
349 : : {
350 : 0 : TCP_SupportAnalyzer::Undelivered(seq, len, orig);
351 : :
352 : : // Re-sync after content gaps.
353 : 0 : InitBuffer();
354 : 0 : resync = true;
355 : 0 : }
356 : :
357 : 0 : void Contents_RPC::DeliverStream(int len, const u_char* data, bool orig)
358 : : {
359 : 0 : TCP_SupportAnalyzer::DeliverStream(len, data, orig);
360 : :
361 [ # # ]: 0 : if ( state == RPC_COMPLETE )
362 : 0 : InitBuffer();
363 : :
364 : : // This is an attempt to re-synchronize the stream with RPC
365 : : // frames after a content gap. We try to look for the beginning
366 : : // of an RPC frame, assuming (1) RPC frames begin at packet
367 : : // boundaries (though they may span over multiple packets) and
368 : : // (2) the first piece is longer than 12 bytes. (If we see a
369 : : // piece shorter than 12 bytes, it is likely that it's the
370 : : // remaining piece of a previous RPC frame, so the code here
371 : : // skips that piece.) It then checks if the frame type and length
372 : : // make any sense, and if so, it assumes that is beginning of
373 : : // a frame.
374 [ # # ][ # # ]: 0 : if ( resync && state == RPC_RECORD_MARKER && buf_n == 0 )
[ # # ]
375 : : {
376 : : // Assuming RPC frames align with packet boundaries ...
377 [ # # ]: 0 : if ( len < 12 )
378 : : {
379 : : // Ignore small fragmeents.
380 : : if ( len != 1 && DEBUG_rpc_resync )
381 : : {
382 : : // One-byte fragments are likely caused by
383 : : // TCP keep-alive retransmissions.
384 : : DEBUG_MSG("%.6f RPC resync: "
385 : : "discard small pieces: %d\n",
386 : : network_time, len);
387 : : Conn()->Weird(
388 : : fmt("RPC resync: discard %d bytes\n",
389 : : len));
390 : : }
391 : 0 : return;
392 : : }
393 : :
394 : 0 : const u_char* xdata = data;
395 : 0 : int xlen = len;
396 : 0 : uint32 frame_len = extract_XDR_uint32(xdata, xlen);
397 : 0 : uint32 xid = extract_XDR_uint32(xdata, xlen);
398 : 0 : uint32 frame_type = extract_XDR_uint32(xdata, xlen);
399 : :
400 [ # # # # ]: 0 : if ( (IsOrig() && frame_type != 0) ||
[ # # ][ # # ]
[ # # ][ # # ]
401 : : (! IsOrig() && frame_type != 1) ||
402 : : frame_len < 16 )
403 : : {
404 : : // Skip this packet.
405 : : if ( DEBUG_rpc_resync )
406 : : {
407 : : DEBUG_MSG("RPC resync: skipping %d bytes\n",
408 : : len);
409 : : }
410 : 0 : return;
411 : : }
412 : :
413 : 0 : resync = false;
414 : : }
415 : :
416 : : int n;
417 [ # # ][ # # ]: 0 : for ( n = 0; buf_n < buf_len && n < len; ++n )
418 : 0 : msg_buf[buf_n++] = data[n];
419 : :
420 [ # # ]: 0 : if ( buf_n < buf_len )
421 : : // Haven't filled up the message buffer yet, no more to do.
422 : 0 : return;
423 : :
424 [ # # # # ]: 0 : switch ( state ) {
425 : : case RPC_RECORD_MARKER:
426 : : { // Have the whole record marker.
427 : 0 : int prev_frag_len = buf_len - 4;
428 : 0 : const u_char* buf = &msg_buf[prev_frag_len];
429 : 0 : int n = 4;
430 : :
431 : 0 : uint32 marker = extract_XDR_uint32(buf, n);
432 [ # # ]: 0 : if ( ! buf )
433 : 0 : internal_error("inconsistent RPC record marker extraction");
434 : :
435 [ # # ][ # # ]: 0 : if ( prev_frag_len > 0 && last_frag )
436 : 0 : internal_error("last_frag set but more fragments");
437 : :
438 : 0 : last_frag = (marker & 0x80000000) != 0;
439 : :
440 : 0 : marker &= 0x7fffffff;
441 : :
442 [ # # ]: 0 : if ( prev_frag_len > 0 )
443 : : // We're adding another fragment.
444 : 0 : marker += prev_frag_len;
445 : :
446 : : // Fragment length is now given by marker. Sanity-check.
447 [ # # ]: 0 : if ( marker > MAX_RPC_LEN )
448 : : {
449 : 0 : Conn()->Weird("excessive_RPC_len");
450 : 0 : marker = MAX_RPC_LEN;
451 : : }
452 : :
453 : : // The new size is either the full record size (if this
454 : : // is the last fragment), or that plus 4 more bytes for
455 : : // the next fragment header.
456 [ # # ]: 0 : int new_size = last_frag ? marker : marker + 4;
457 : :
458 : 0 : u_char* tmp = new u_char[new_size];
459 [ # # ]: 0 : int msg_len = (unsigned int) buf_len < marker ? buf_len : marker;
460 [ # # ]: 0 : for ( int i = 0; i < msg_len; ++i )
461 : 0 : tmp[i] = msg_buf[i];
462 : :
463 [ # # ]: 0 : delete [] msg_buf;
464 : 0 : msg_buf = tmp;
465 : :
466 : 0 : buf_len = marker; // we only want to fill to here
467 : 0 : buf_n = prev_frag_len; // overwrite this fragment's header
468 : :
469 : 0 : state = RPC_MESSAGE_BUFFER;
470 : : }
471 : 0 : break;
472 : :
473 : : case RPC_MESSAGE_BUFFER:
474 : : { // Have the whole fragment.
475 [ # # ]: 0 : if ( ! last_frag )
476 : : {
477 : : // We earlier made sure to leave an extra 4 bytes
478 : : // at the end of the buffer - use them now for
479 : : // the new fragment header.
480 : 0 : buf_len += 4;
481 : 0 : state = RPC_RECORD_MARKER;
482 : 0 : break;
483 : : }
484 : :
485 [ # # ]: 0 : if ( ! interp->DeliverRPC(msg_buf, buf_n, IsOrig()) )
486 : 0 : Conn()->Weird("partial_RPC");
487 : :
488 : 0 : state = RPC_COMPLETE;
489 [ # # ]: 0 : delete [] msg_buf;
490 : 0 : msg_buf = 0;
491 : : }
492 : 0 : break;
493 : :
494 : : case RPC_COMPLETE:
495 : 0 : internal_error("RPC state inconsistency");
496 : : }
497 : :
498 [ # # ]: 0 : if ( n < len )
499 : : // More data to munch on.
500 : 0 : DeliverStream(len - n, data + n, orig);
501 : : }
502 : :
503 : : RPC_Analyzer::RPC_Analyzer(AnalyzerTag::Tag tag, Connection* conn,
504 : 0 : RPC_Interpreter* arg_interp)
505 : 0 : : TCP_ApplicationAnalyzer(tag, conn)
506 : : {
507 : 0 : interp = arg_interp;
508 : :
509 [ # # # # ]: 0 : if ( Conn()->ConnTransport() == TRANSPORT_UDP )
510 : 0 : ADD_ANALYZER_TIMER(&RPC_Analyzer::ExpireTimer,
511 : : network_time + rpc_timeout, 1, TIMER_RPC_EXPIRE);
512 : 0 : }
513 : :
514 : 0 : RPC_Analyzer::~RPC_Analyzer()
515 : : {
516 [ # # ][ # # ]: 0 : delete interp;
[ # # ]
517 [ # # ][ # # ]: 0 : }
[ # # ]
518 : :
519 : : void RPC_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
520 : 0 : int seq, const IP_Hdr* ip, int caplen)
521 : : {
522 : 0 : TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
523 : :
524 [ # # ]: 0 : if ( orig )
525 : : {
526 [ # # ]: 0 : if ( ! interp->DeliverRPC(data, len, 1) )
527 : 0 : Weird("bad_RPC");
528 : : }
529 : : else
530 : : {
531 [ # # ]: 0 : if ( ! interp->DeliverRPC(data, len, 0) )
532 : 0 : Weird("bad_RPC");
533 : : }
534 : 0 : }
535 : :
536 : 0 : void RPC_Analyzer::Done()
537 : : {
538 : 0 : TCP_ApplicationAnalyzer::Done();
539 : :
540 : : // This code was replicated in NFS.cc and Portmap.cc, so we factor
541 : : // it into here. The semantics have slightly changed - it used
542 : : // to be we'd always execute interp->Timeout(), but now we only
543 : : // do for UDP.
544 : :
545 [ # # # # ]: 0 : if ( Conn()->ConnTransport() == TRANSPORT_TCP && TCP() )
[ # # ]
546 : : {
547 [ # # ][ # # ]: 0 : if ( orig_rpc->State() != RPC_COMPLETE &&
[ # # ][ # # ]
[ # # ]
548 : : (TCP()->OrigState() == TCP_ENDPOINT_CLOSED ||
549 : : TCP()->OrigPrevState() == TCP_ENDPOINT_CLOSED) &&
550 : : // Sometimes things like tcpwrappers will immediately
551 : : // close the connection, without any data having been
552 : : // transferred. Don't bother flagging these.
553 : : TCP()->Orig()->Size() > 0 )
554 : 0 : Weird("partial_RPC_request");
555 : : }
556 : : else
557 : 0 : interp->Timeout();
558 : 0 : }
559 : :
560 : 0 : void RPC_Analyzer::ExpireTimer(double /* t */)
561 : : {
562 : 0 : Event(connection_timeout);
563 : 0 : sessions->Remove(Conn());
564 : 0 : }
565 : :
566 : : // The binpac version of interpreter.
567 : : #include "rpc_pac.h"
568 : :
569 : 0 : RPC_UDP_Analyzer_binpac::RPC_UDP_Analyzer_binpac(Connection* conn)
570 : 0 : : Analyzer(AnalyzerTag::RPC_UDP_BINPAC, conn)
571 : : {
572 : 0 : interp = new binpac::SunRPC::RPC_Conn(this);
573 : 0 : ADD_ANALYZER_TIMER(&RPC_UDP_Analyzer_binpac::ExpireTimer,
574 : : network_time + rpc_timeout, 1, TIMER_RPC_EXPIRE);
575 : 0 : }
576 : :
577 : 0 : RPC_UDP_Analyzer_binpac::~RPC_UDP_Analyzer_binpac()
578 : : {
579 [ # # ][ # # ]: 0 : delete interp;
[ # # ]
580 [ # # ][ # # ]: 0 : }
[ # # ]
581 : :
582 : 0 : void RPC_UDP_Analyzer_binpac::Done()
583 : : {
584 : 0 : Analyzer::Done();
585 : 0 : interp->Timeout();
586 : 0 : }
587 : :
588 : 0 : void RPC_UDP_Analyzer_binpac::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen)
589 : : {
590 : 0 : Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
591 : : try
592 : : {
593 : 0 : interp->NewData(orig, data, data + len);
594 : : }
595 : 0 : catch ( binpac::Exception &e )
596 : : {
597 : 0 : Weird(fmt("bad_RPC: %s", e.msg().c_str()));
598 : : }
599 : 0 : }
600 : :
601 : 0 : void RPC_UDP_Analyzer_binpac::ExpireTimer(double /* t */)
602 : : {
603 : 0 : Event(connection_timeout);
604 : 0 : sessions->Remove(Conn());
605 [ + - ][ + - ]: 6 : }
|