📄 fromdump.cc
字号:
voidFromDump::set_active(bool active){ _active = active; if (active) { if (output_is_push(0) && !_task.scheduled()) _task.reschedule(); else if (!output_is_push(0)) _notifier.wake(); }}voidFromDump::prepare_times(const Timestamp &ts){ if (_first_time_relative) _first_time += ts; if (_last_time_relative) _last_time += ts; else if (_last_time_interval) _last_time += _first_time; if (_timing) _time_offset = Timestamp::now() - ts; _have_any_times = true;}boolFromDump::read_packet(ErrorHandler *errh){ fake_pcap_pkthdr swapped_ph; const fake_pcap_pkthdr *ph; const Timestamp *ts_ptr; int len, caplen, skiplen = 0; Packet *p; assert(!_packet); // record file position _packet_filepos = _ff.file_pos(); // read the packet header if (!(ph = reinterpret_cast<const fake_pcap_pkthdr *>(_ff.get_aligned(sizeof(*ph), &swapped_ph)))) return false; if (_swapped) { swap_packet_header(ph, &swapped_ph); ph = &swapped_ph; } // may need to swap 'caplen' and 'len' fields at or before version 2.3 if (_minor_version > 3 || (_minor_version == 3 && ph->caplen <= ph->len)) { len = ph->len; caplen = ph->caplen; } else { len = ph->caplen; caplen = ph->len; } // check for errors // 3.Jul.2002 -- Angelos Stavrou discovered that tcptrace-generated // tcpdump files store an incorrect caplen. It's only off by one. Tcptrace // should be fixed, but we hack around the problem here, as does // tcpdump itself. if (caplen > 65535) { _ff.error(errh, "bad packet header; giving up"); return false; } else if (caplen > len) { skiplen = caplen - len; caplen = len; } // compensate for modified pcap versions _ff.shift_pos(_extra_pkthdr_crap); // check times check_times: ts_ptr = fake_bpf_timeval_union::make_timestamp(&ph->ts, &swapped_ph.ts); if (!_have_any_times) prepare_times(*ts_ptr); if (_have_first_time) { if (*ts_ptr < _first_time) { _ff.shift_pos(caplen + skiplen); return true; } else _have_first_time = false; } if (_have_last_time && *ts_ptr >= _last_time) { _have_last_time = false; (void) _end_h->call_write(errh); if (!_active) { _ff.shift_pos(caplen + skiplen); return false; } // retry _last_time in case someone changed it goto check_times; } // checking sampling probability if (_sampling_prob < (1 << SAMPLING_SHIFT) && (click_random() & ((1<<SAMPLING_SHIFT)-1)) >= _sampling_prob) { _ff.shift_pos(caplen + skiplen); return true; } // create packet p = _ff.get_packet(caplen, ts_ptr->sec(), ts_ptr->subsec(), errh); if (!p) return false; SET_EXTRA_LENGTH_ANNO(p, len - caplen); _ff.shift_pos(skiplen); p->set_mac_header(p->data()); _packet = p; return true;}voidFromDump::run_timer(Timer *){ if (_active) { if (output_is_push(0)) _task.reschedule(); else _notifier.wake(); }}boolFromDump::run_task(Task *){ if (!_active) return false; int retry_count = 0; again: if (!_packet && !read_packet(0)) { if (_end_h) _end_h->call_write(ErrorHandler::default_handler()); return false; } if (_packet && _timing) { Timestamp now = Timestamp::now(); Timestamp t = _packet->timestamp_anno() + _time_offset; if (now < t) { t -= Timer::adjustment(); if (now < t) _timer.schedule_at(t); else _task.fast_reschedule(); return false; } } if (_packet && _force_ip && !fake_pcap_force_ip(_packet, _linktype)) { checked_output_push(1, _packet); _packet = 0; } if (!_packet && ++retry_count < 16) goto again; _task.fast_reschedule(); if (_packet) { output(0).push(_packet); _count++; _packet = 0; return true; } else return false;}Packet *FromDump::pull(int){ if (!_active) { _notifier.sleep(); return 0; } bool more = true; if (!_packet) more = read_packet(0); if (_packet && _timing) { Timestamp now = Timestamp::now(); Timestamp t = _packet->timestamp_anno() + _time_offset; if (t > now) { t -= Timestamp::make_msec(50); if (t > now) { _timer.schedule_at(t); _notifier.sleep(); } return 0; } } if (_packet && _force_ip && !fake_pcap_force_ip(_packet, _linktype)) { checked_output_push(1, _packet); _packet = 0; } // notify presence/absence of more packets _notifier.set_active(more, true); if (!more && _end_h) _end_h->call_write(ErrorHandler::default_handler()); if (Packet *p = _packet) { _count++; _packet = 0; return p; } else return 0;}enum { H_SAMPLING_PROB, H_ACTIVE, H_ENCAP, H_STOP, H_PACKET_FILEPOS, H_EXTEND_INTERVAL, H_COUNT, H_RESET_COUNTS, H_RESET_TIMING};StringFromDump::read_handler(Element *e, void *thunk){ FromDump *fd = static_cast<FromDump *>(e); switch ((intptr_t)thunk) { case H_SAMPLING_PROB: return cp_unparse_real2(fd->_sampling_prob, SAMPLING_SHIFT); case H_ENCAP: return String(fake_pcap_unparse_dlt(fd->_linktype)); default: return "<error>"; }}intFromDump::write_handler(const String &s_in, Element *e, void *thunk, ErrorHandler *errh){ FromDump *fd = static_cast<FromDump *>(e); String s = cp_uncomment(s_in); switch ((intptr_t)thunk) { case H_ACTIVE: { bool active; if (cp_bool(s, &active)) { fd->set_active(active); return 0; } else return errh->error("'active' should be Boolean"); } case H_STOP: fd->set_active(false); fd->router()->please_stop_driver(); return 0; case H_EXTEND_INTERVAL: { Timestamp ts; if (cp_time(s, &ts)) { fd->_last_time += ts; if (fd->_end_h) fd->_have_last_time = true, fd->set_active(true); return 0; } else return errh->error("'extend_interval' takes a time interval"); } case H_RESET_COUNTS: fd->_count = 0; return 0; case H_RESET_TIMING: fd->_first_time_relative = false; fd->_last_time_relative = fd->_last_time_interval = false; fd->_have_any_times = false; return 0; default: return -EINVAL; }}voidFromDump::add_handlers(){ _ff.add_handlers(this, true); add_read_handler("sampling_prob", read_handler, (void *)H_SAMPLING_PROB); add_data_handlers("active", Handler::OP_READ | Handler::CHECKBOX, &_active); add_write_handler("active", write_handler, (void *)H_ACTIVE); add_read_handler("encap", read_handler, (void *)H_ENCAP); add_write_handler("stop", write_handler, (void *)H_STOP, Handler::BUTTON); add_data_handlers("packet_filepos", Handler::OP_READ, &_packet_filepos); add_write_handler("extend_interval", write_handler, (void *)H_EXTEND_INTERVAL); add_data_handlers("count", Handler::OP_READ, &_count); add_write_handler("reset_counts", write_handler, (void *)H_RESET_COUNTS, Handler::BUTTON); add_write_handler("reset_timing", write_handler, (void *)H_RESET_TIMING, Handler::BUTTON); if (output_is_push(0)) add_task_handlers(&_task);}CLICK_ENDDECLSELEMENT_REQUIRES(userlevel|ns FakePcap FromFile)EXPORT_ELEMENT(FromDump)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -