📄 fromdump.cc
字号:
_linktype = o->_linktype; if (_linktype == FAKE_DLT_RAW) _force_ip = true; else if (_force_ip && !fake_pcap_dlt_force_ipable(_linktype)) _ff.warning(errh, "unknown linktype %d; can't force IP packets", _linktype); _time_offset = o->_time_offset; _packet_filepos = o->_packet_filepos;}voidFromDump::cleanup(CleanupStage){ _ff.cleanup(); if (_packet) _packet->kill(); _packet = 0;}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_listeners(); }}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; int tries = 0; assert(!_packet); retry: // quit if we have tried too many times tries++; if ((tries % 16) == 0 && output_is_push(0)) return true; // 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::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); goto retry; } 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) && (uint32_t)(random() & ((1<<SAMPLING_SHIFT)-1)) >= _sampling_prob) { _ff.shift_pos(caplen + skiplen); goto retry; } // 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()); if (_force_ip && !fake_pcap_force_ip(p, _linktype)) { checked_output_push(1, p); goto retry; } _packet = p; return true;}boolFromDump::run_task(){ if (!_active) return false; bool more = true; if (!_packet) more = read_packet(0); if (_packet && _timing) if (_packet->timestamp_anno() > Timestamp::now() - _time_offset) { _task.fast_reschedule(); return false; } if (more) _task.fast_reschedule(); else if (_end_h) _end_h->call_write(ErrorHandler::default_handler()); if (_packet) { output(0).push(_packet); _packet = 0; return true; } else return false;}Packet *FromDump::pull(int){ if (!_active) { _notifier.sleep_listeners(); return 0; } bool more = true; if (!_packet) more = read_packet(0); if (_packet && _timing) if (_packet->timestamp_anno() > Timestamp::now() - _time_offset) return 0; // notify presence/absence of more packets _notifier.set_listeners(more); if (!more && _end_h) _end_h->call_write(ErrorHandler::default_handler()); Packet *p = _packet; _packet = 0; return p;}enum { H_SAMPLING_PROB, H_ACTIVE, H_ENCAP, H_STOP, H_PACKET_FILEPOS, H_EXTEND_INTERVAL};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) + "\n"; case H_ACTIVE: return cp_unparse_bool(fd->_active) + "\n"; case H_ENCAP: return String(fake_pcap_unparse_dlt(fd->_linktype)) + "\n"; case H_PACKET_FILEPOS: return String(fd->_packet_filepos) + "\n"; default: return "<error>\n"; }}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"); } default: return -EINVAL; }}voidFromDump::add_handlers(){ _ff.add_handlers(this, true); add_read_handler("sampling_prob", read_handler, (void *)H_SAMPLING_PROB); add_read_handler("active", read_handler, (void *)H_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); add_read_handler("packet_filepos", read_handler, (void *)H_PACKET_FILEPOS); add_write_handler("extend_interval", write_handler, (void *)H_EXTEND_INTERVAL); 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 + -