📄 fromipsumdump.cc
字号:
// -*- mode: c++; c-basic-offset: 4 -*-/* * fromipsumdump.{cc,hh} -- element reads packets from IP summary dump file * Eddie Kohler * * Copyright (c) 2001 International Computer Science Institute * Copyright (c) 2008 Meraki, Inc. * * 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 "fromipsumdump.hh"#include <click/confparse.hh>#include <click/router.hh>#include <click/standard/scheduleinfo.hh>#include <click/error.hh>#include <click/glue.hh>#include <click/straccum.hh>#include <clicknet/ip.h>#include <clicknet/udp.h>#include <clicknet/tcp.h>#include <clicknet/icmp.h>#include <click/packet_anno.hh>#include <click/nameinfo.hh>#include <click/userutils.hh>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>CLICK_DECLS#ifdef i386# define GET4(p) ntohl(*reinterpret_cast<const uint32_t *>((p)))# define GET2(p) ntohs(*reinterpret_cast<const uint16_t *>((p)))#else# define GET4(p) (((p)[0]<<24) | ((p)[1]<<16) | ((p)[2]<<8) | (p)[3])# define GET2(p) (((p)[0]<<8) | (p)[1])#endif#define GET1(p) ((p)[0])FromIPSummaryDump::FromIPSummaryDump() : _work_packet(0), _task(this), _timer(this){ _ff.set_landmark_pattern("%f:%l");}FromIPSummaryDump::~FromIPSummaryDump(){}void *FromIPSummaryDump::cast(const char *n){ if (strcmp(n, Notifier::EMPTY_NOTIFIER) == 0 && !output_is_push(0)) return static_cast<Notifier *>(&_notifier); else return Element::cast(n);}intFromIPSummaryDump::configure(Vector<String> &conf, ErrorHandler *errh){ bool stop = false, active = true, zero = true, checksum = false, multipacket = false, timing = false; uint8_t default_proto = IP_PROTO_TCP; _sampling_prob = (1 << SAMPLING_SHIFT); String default_contents, default_flowid; if (cp_va_kparse(conf, this, errh, "FILENAME", cpkP+cpkM, cpFilename, &_ff.filename(), "STOP", 0, cpBool, &stop, "ACTIVE", 0, cpBool, &active, "ZERO", 0, cpBool, &zero, "TIMING", 0, cpBool, &timing, "CHECKSUM", 0, cpBool, &checksum, "SAMPLE", 0, cpUnsignedReal2, SAMPLING_SHIFT, &_sampling_prob, "PROTO", 0, cpByte, &default_proto, "MULTIPACKET", 0, cpBool, &multipacket, "DEFAULT_CONTENTS", 0, cpArgument, &default_contents, "DEFAULT_FLOWID", 0, cpArgument, &default_flowid, "CONTENTS", 0, cpArgument, &default_contents, "FLOWID", 0, cpArgument, &default_flowid, cpEnd) < 0) return -1; if (_sampling_prob > (1 << SAMPLING_SHIFT)) { errh->warning("SAMPLE probability reduced to 1"); _sampling_prob = (1 << SAMPLING_SHIFT); } else if (_sampling_prob == 0) errh->warning("SAMPLE probability is 0; emitting no packets"); _default_proto = default_proto; _stop = stop; _active = active; _zero = zero; _checksum = checksum; _timing = timing; _have_timing = false; _multipacket = multipacket; _have_flowid = _have_aggregate = _binary = false; if (default_contents) bang_data(default_contents, errh); if (default_flowid) bang_flowid(default_flowid, errh); return 0;}intFromIPSummaryDump::read_binary(String &result, ErrorHandler *errh){ assert(_binary); uint8_t record_storage[4]; const uint8_t *record = _ff.get_unaligned(4, record_storage, errh); if (!record) return 0; int record_length = GET4(record) & 0x7FFFFFFFU; if (record_length < 4) return _ff.error(errh, "binary record too short"); bool textual = (record[0] & 0x80 ? true : false); result = _ff.get_string(record_length - 4, errh); if (!result) return 0; if (textual) { const char *s = result.begin(), *e = result.end(); while (e > s && e[-1] == 0) e--; if (e != result.end()) result = result.substring(s, e); } _ff.set_lineno(_ff.lineno() + 1); return (textual ? 2 : 1);}intFromIPSummaryDump::initialize(ErrorHandler *errh){ // make sure notifier is initialized if (!output_is_push(0)) _notifier.initialize(Notifier::EMPTY_NOTIFIER, router()); _timer.initialize(this); if (_ff.initialize(errh) < 0) return -1; _minor_version = IPSummaryDump::MINOR_VERSION; // expected minor version String line; if (_ff.peek_line(line, errh, true) < 0) return -1; else if (line.substring(0, 14) == "!IPSummaryDump") { int major_version; if (sscanf(line.c_str() + 14, " %d.%d", &major_version, &_minor_version) == 2) { if (major_version != IPSummaryDump::MAJOR_VERSION || _minor_version > IPSummaryDump::MINOR_VERSION) { _ff.warning(errh, "unexpected IPSummaryDump version %d.%d", major_version, _minor_version); _minor_version = IPSummaryDump::MINOR_VERSION; } } (void) _ff.read_line(line, errh, true); // throw away line } else { // parse line again, warn if this doesn't look like a dump if (!line.substring(0, 8).equals("!creator", 8) && !line.substring(0, 5).equals("!data", 5) && !line.substring(0, 9).equals("!contents", 9) && !line.substring(0, 6).equals("!proto", 6) && !line.substring(0, 7).equals("!flowid", 7)) { if (!_fields.size() /* don't warn on DEFAULT_CONTENTS */) _ff.warning(errh, "missing banner line; is this an IP summary dump?"); } } _format_complaint = false; if (output_is_push(0)) ScheduleInfo::initialize_task(this, &_task, _active, errh); return 0;}voidFromIPSummaryDump::cleanup(CleanupStage){ _ff.cleanup(); if (_work_packet) _work_packet->kill(); _work_packet = 0;}intFromIPSummaryDump::sort_fields_compare(const void *ap, const void *bp, void *user_data){ int a = *reinterpret_cast<const int *>(ap); int b = *reinterpret_cast<const int *>(bp); FromIPSummaryDump *f = reinterpret_cast<FromIPSummaryDump *>(user_data); const IPSummaryDump::FieldReader *fa = f->_fields[a]; const IPSummaryDump::FieldReader *fb = f->_fields[b]; if (fa->order < fb->order) return -1; if (fa->order > fb->order) return 1; return (a < b ? -1 : (a == b ? 0 : 1));}voidFromIPSummaryDump::bang_data(const String &line, ErrorHandler *errh){ Vector<String> words; cp_spacevec(line, words); _fields.clear(); _field_order.clear(); for (int i = 0; i < words.size(); i++) { String word = cp_unquote(words[i]); if (i == 0 && (word == "!data" || word == "!contents")) continue; const IPSummaryDump::FieldReader *f = IPSummaryDump::FieldReader::find(word); if (!f) { _ff.warning(errh, "unknown content type '%s'", word.c_str()); f = &IPSummaryDump::null_reader; } else if (!f->inject) { _ff.warning(errh, "content type '%s' ignored on input", word.c_str()); f = &IPSummaryDump::null_reader; } _fields.push_back(f); _field_order.push_back(_fields.size() - 1); } if (_fields.size() == 0) _ff.error(errh, "no contents specified"); click_qsort(_field_order.begin(), _fields.size(), sizeof(int), sort_fields_compare, this);}voidFromIPSummaryDump::bang_proto(const String &line, const char *type, ErrorHandler *errh){ Vector<String> words; cp_spacevec(line, words); int proto; if (words.size() != 2) _ff.error(errh, "bad %s", type); else if (cp_integer(words[1], &proto) && proto < 256) _default_proto = proto; else if (words[1] == "T") _default_proto = IP_PROTO_TCP; else if (words[1] == "U") _default_proto = IP_PROTO_UDP; else if (words[1] == "I") _default_proto = IP_PROTO_ICMP; else _ff.error(errh, "bad protocol in %s", type);}voidFromIPSummaryDump::bang_flowid(const String &line, ErrorHandler *errh){ Vector<String> words; cp_spacevec(line, words); IPAddress src, dst; uint32_t sport = 0, dport = 0; if (words.size() < 5 || (!cp_ip_address(words[1], &src) && words[1] != "-") || (!cp_integer(words[2], &sport) && words[2] != "-") || (!cp_ip_address(words[3], &dst) && words[3] != "-") || (!cp_integer(words[4], &dport) && words[4] != "-") || sport > 65535 || dport > 65535) { _ff.error(errh, "bad !flowid specification"); _have_flowid = false; } else { if (words.size() >= 6) bang_proto(String::make_stable("! ", 2) + words[5], "!flowid", errh); _given_flowid = IPFlowID(src, htons(sport), dst, htons(dport)); _have_flowid = true; }}voidFromIPSummaryDump::bang_aggregate(const String &line, ErrorHandler *errh){ Vector<String> words; cp_spacevec(line, words); if (words.size() != 2 || !cp_integer(words[1], &_aggregate)) { _ff.error(errh, "bad !aggregate specification"); _have_aggregate = false; } else _have_aggregate = true;}voidFromIPSummaryDump::bang_binary(const String &line, ErrorHandler *errh){ Vector<String> words; cp_spacevec(line, words); if (words.size() != 1) _ff.error(errh, "bad !binary specification"); _binary = true; _ff.set_landmark_pattern("%f:record %l"); _ff.set_lineno(1);}static voidset_checksums(WritablePacket *q, click_ip *iph){ assert(iph == q->ip_header()); iph->ip_sum = 0; iph->ip_sum = click_in_cksum((uint8_t *)iph, iph->ip_hl << 2); if (IP_ISFRAG(iph)) /* nada */; else if (iph->ip_p == IP_PROTO_TCP) { click_tcp *tcph = q->tcp_header(); tcph->th_sum = 0; unsigned csum = click_in_cksum((uint8_t *)tcph, q->transport_length()); tcph->th_sum = click_in_cksum_pseudohdr(csum, iph, q->transport_length()); } else if (iph->ip_p == IP_PROTO_UDP) { click_udp *udph = q->udp_header(); udph->uh_sum = 0; unsigned csum = click_in_cksum((uint8_t *)udph, q->transport_length()); udph->uh_sum = click_in_cksum_pseudohdr(csum, iph, q->transport_length()); }}Packet *FromIPSummaryDump::read_packet(ErrorHandler *errh){ // read non-packet lines bool binary; String line; const char *data; const char *end; while (1) { if ((binary = _binary)) { int result = read_binary(line, errh); if (result <= 0) goto eof; else binary = (result == 1); } else if (_ff.read_line(line, errh, true) <= 0) { eof: _ff.cleanup(); return 0; } data = line.begin(); end = line.end(); if (data == end) /* do nothing */; else if (binary || (data[0] != '!' && data[0] != '#')) /* real packet */ break; // parse bang lines if (data[0] == '!') { if (data + 6 <= end && memcmp(data, "!data", 5) == 0 && isspace((unsigned char) data[5])) bang_data(line, errh); else if (data + 8 <= end && memcmp(data, "!flowid", 7) == 0 && isspace((unsigned char) data[7])) bang_flowid(line, errh); else if (data + 7 <= end && memcmp(data, "!proto", 6) == 0 && isspace((unsigned char) data[6])) bang_proto(line, "!proto", errh); else if (data + 11 <= end && memcmp(data, "!aggregate", 10) == 0 && isspace((unsigned char) data[10])) bang_aggregate(line, errh); else if (data + 8 <= end && memcmp(data, "!binary", 7) == 0 && isspace((unsigned char) data[7])) bang_binary(line, errh); else if (data + 10 <= end && memcmp(data, "!contents", 9) == 0 && isspace((unsigned char) data[9])) bang_data(line, errh); } } // read packet data WritablePacket *q = Packet::make(16, (const unsigned char *) 0, 0, 1000); if (!q) { _ff.error(errh, strerror(ENOMEM)); return 0; } if (_zero) memset(q->buffer(), 0, q->buffer_length()); // prepare packet data StringAccum sa; IPSummaryDump::PacketOdesc d(this, q, _default_proto, (_have_flowid ? &_flowid : 0), _minor_version); int nfields = 0; // new code goes here
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -