⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 todump.cc

📁 Click is a modular router toolkit. To use it you ll need to know how to compile and install the sof
💻 CC
字号:
// -*- mode: c++; c-basic-offset: 4 -*-/* * todump.{cc,hh} -- element writes packets to tcpdump-like file * John Jannotti, Eddie Kohler * * Copyright (c) 1999-2000 Massachusetts Institute of Technology * Copyright (c) 2000 Mazu Networks, Inc. * Copyright (c) 2007 Regents of the University of California * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include <click/glue.hh>#include "todump.hh"#include <click/confparse.hh>#include <click/router.hh>#if CLICK_NS# include <click/master.hh>#endif#include <click/error.hh>#include <click/standard/scheduleinfo.hh>#include <click/packet_anno.hh>#include "fakepcap.hh"#include <click/userutils.hh>CLICK_DECLSToDump::ToDump()    : _fp(0), _count(0), _task(this), _use_encap_from(0){}ToDump::~ToDump(){}intToDump::configure(Vector<String> &conf, ErrorHandler *errh){    String encap_type;    String use_encap_from;    _snaplen = 2000;    _extra_length = true;#if CLICK_NS    bool per_node = false;#endif    if (cp_va_kparse(conf, this, errh,		     "FILENAME", cpkP+cpkM, cpFilename, &_filename,		     "SNAPLEN", cpkP, cpUnsigned, &_snaplen,		     "ENCAP", cpkP, cpWord, &encap_type,		     "USE_ENCAP_FROM", 0, cpArgument, &use_encap_from,		     "EXTRA_LENGTH", 0, cpBool, &_extra_length,#if CLICK_NS		     "PER_NODE", 0, cpBool, &per_node,#endif		     cpEnd) < 0)	return -1;    if (_snaplen == 0)	_snaplen = 0xFFFFFFFFU;    if (use_encap_from && encap_type)	return errh->error("specify at most one of 'ENCAP' and 'USE_ENCAP_FROM'");    else if (use_encap_from) {	Vector<String> words;	cp_spacevec(use_encap_from, words);	_use_encap_from = new Element *[words.size() + 1];	for (int i = 0; i < words.size(); i++)	    if (!(_use_encap_from[i] = router()->find(words[i], this, errh)))		return -1;	_use_encap_from[words.size()] = 0;	if (words.size() == 0)	    return errh->error("element names missing after 'USE_ENCAP_FROM'");    } else if (!encap_type)	_linktype = FAKE_DLT_EN10MB;    else if ((_linktype = fake_pcap_parse_dlt(encap_type)) < 0)	return errh->error("bad encapsulation type");#if CLICK_NS    if (per_node) {	char tmp[255];	int r = simclick_sim_command(router()->simnode(), SIMCLICK_GET_NODE_NAME,tmp,255);	if (r >= 0)	    _filename = String(tmp) + String("_") + _filename;    }#endif    return 0;}ToDump *ToDump::hotswap_element() const{    if (Element *e = Element::hotswap_element())	if (ToDump *td = (ToDump *)e->cast("ToDump"))	    if (td->_filename == _filename		&& td->_linktype == _linktype)		return td;    return 0;}intToDump::initialize(ErrorHandler *errh){    // check _use_encap_from    if (_use_encap_from) {	_linktype = -1;	// collect encap types	Vector<String> encap_types;	for (int i = 0; _use_encap_from[i]; i++) {	    const Handler *h = Router::handler(_use_encap_from[i], "encap");	    if (!h || !h->readable())		return errh->error("'%{element}' has no 'encap' read handler", _use_encap_from[i]);	    encap_types.push_back(cp_uncomment(h->call_read(_use_encap_from[i])));	}	// parse encap types	for (int i = 0; i < encap_types.size(); i++) {	    int et = fake_pcap_parse_dlt(encap_types[i]);	    if (et < 0)		return errh->error("'%{element}.encap' did not return a valid encapsulation type", _use_encap_from[i]);	    else if (_linktype >= 0 && et != _linktype) {		errh->error("source encapsulation types disagree:");		for (int j = 0; j < encap_types.size(); j++)		    errh->error("  %s has %s\n", _use_encap_from[j]->declaration().c_str(), encap_types[j].c_str());		return -EINVAL;	    } else		_linktype = et;	}    }    // skip initialization if we're hotswapping later    if (!hotswap_element()) {	// prepare files	assert(!_fp);	if (_filename != "-") {	    if (compressed_filename(_filename) > 0)		_fp = open_compress_pipe(_filename, errh);	    else		_fp = fopen(_filename.c_str(), "wb");	    if (!_fp)		return errh->error("%s: %s", _filename.c_str(), strerror(errno));	} else {	    _fp = stdout;	    _filename = "<stdout>";	}	struct fake_pcap_file_header h;	h.magic = FAKE_PCAP_MAGIC;	h.version_major = FAKE_PCAP_VERSION_MAJOR;	h.version_minor = FAKE_PCAP_VERSION_MINOR;	h.thiszone = 0;		// timestamps are in GMT	h.sigfigs = 0;		// XXX accuracy of timestamps?	h.snaplen = _snaplen;	h.linktype = _linktype;	size_t wrote_header = fwrite(&h, sizeof(h), 1, _fp);	if (wrote_header != 1)	    return errh->error("%s: unable to write file header", _filename.c_str());    }    if (input_is_pull(0) && noutputs() == 0) {	ScheduleInfo::join_scheduler(this, &_task, errh);	_signal = Notifier::upstream_empty_signal(this, 0, &_task);    }    _active = true;    return 0;}voidToDump::take_state(Element *e, ErrorHandler *){    ToDump *td = static_cast<ToDump *>(e); // result of hotswap_element()    _fp = td->_fp;    td->_fp = 0;}voidToDump::cleanup(CleanupStage){    if (_fp && _fp != stdout)	fclose(_fp);    _fp = 0;}voidToDump::write_packet(Packet *p){    struct fake_pcap_pkthdr ph;    const Timestamp& ts = p->timestamp_anno();    if (!ts) {	Timestamp now = Timestamp::now();	ph.ts.tv.tv_sec = now.sec();	ph.ts.tv.tv_usec = now.usec();    } else {	ph.ts.tv.tv_sec = ts.sec();	ph.ts.tv.tv_usec = ts.usec();    }    unsigned to_write = p->length();    ph.len = to_write + (_extra_length ? EXTRA_LENGTH_ANNO(p) : 0);    if (_snaplen && to_write > _snaplen)	to_write = _snaplen;    ph.caplen = to_write;    // XXX writing to pipe?    if (fwrite(&ph, sizeof(ph), 1, _fp) == 0	|| fwrite(p->data(), 1, to_write, _fp) == 0) {	if (errno != EAGAIN) {	    _active = false;	    click_chatter("ToDump(%s): %s", _filename.c_str(), strerror(errno));	}    } else	_count++;}voidToDump::push(int, Packet *p){    if (_active)	write_packet(p);    checked_output_push(0, p);}Packet *ToDump::pull(int){    Packet *p = input(0).pull();    if (_active && p)	write_packet(p);    return p;}boolToDump::run_task(Task *){    if (!_active)	return false;    Packet *p = input(0).pull();    if (p) {	write_packet(p);	p->kill();    } else if (!_signal)	return false;    _task.fast_reschedule();    return p != 0;}enum { H_FILENAME = 0, H_COUNT = 1, H_RESET_COUNTS = 2 };StringToDump::read_handler(Element *e, void *thunk){    ToDump *td = static_cast<ToDump *>(e);    switch ((uintptr_t) thunk) {    case H_FILENAME:	return td->_filename;    case H_COUNT:	return String(td->_count);    default:	return "<error>";    }}intToDump::write_handler(const String &, Element *e, void *, ErrorHandler *){    ToDump *td = static_cast<ToDump *>(e);    td->_count = 0;    return 0;}voidToDump::add_handlers(){    add_read_handler("filename", read_handler, (void *)H_FILENAME);    add_read_handler("count", read_handler, (void *)H_COUNT);    add_write_handler("reset_counts", write_handler, (void *)H_RESET_COUNTS, Handler::BUTTON);    if (input_is_pull(0) && noutputs() == 0)	add_task_handlers(&_task);}CLICK_ENDDECLSELEMENT_REQUIRES(userlevel|ns FakePcap)EXPORT_ELEMENT(ToDump)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -