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

📄 fromtcpdump.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
📖 第 1 页 / 共 2 页
字号:
// -*- mode: c++; c-basic-offset: 4 -*-/* * fromtcpdump.{cc,hh} -- element reads packets from IP summary dump file * Eddie Kohler * * Copyright (c) 2003 International Computer Science Institute * * 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 "fromtcpdump.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 <click/packet_anno.hh>#include <click/userutils.hh>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>CLICK_DECLSFromTcpdump::FromTcpdump()    : Element(0, 1), _task(this){    _ff.set_landmark_pattern("%f:%l");}FromTcpdump::~FromTcpdump(){}void *FromTcpdump::cast(const char *n){    if (strcmp(n, Notifier::EMPTY_NOTIFIER) == 0 && !output_is_push(0)) {	_notifier.initialize(router());	return static_cast<Notifier *>(&_notifier);    } else	return Element::cast(n);}intFromTcpdump::configure(Vector<String> &conf, ErrorHandler *errh){    bool stop = false, active = true, zero = true, checksum = false;    _sampling_prob = (1 << SAMPLING_SHIFT);    _absolute_seq = -1;        if (cp_va_parse(conf, this, errh,		    cpFilename, "dump file name", &_ff.filename(),		    cpKeywords,		    "STOP", cpBool, "stop driver when done?", &stop,		    "ACTIVE", cpBool, "start active?", &active,		    "ZERO", cpBool, "zero packet data?", &zero,		    "CHECKSUM", cpBool, "set packet checksums?", &checksum,		    "SAMPLE", cpUnsignedReal2, "sampling probability", SAMPLING_SHIFT, &_sampling_prob,		    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");    _stop = stop;    _active = active;    _zero = zero;    _checksum = checksum;    _dead = false;    return 0;}intFromTcpdump::initialize(ErrorHandler *errh){    // make sure notifier is initialized    if (!output_is_push(0))	_notifier.initialize(router());    if (_ff.initialize(errh) < 0)	return -1;    // read a line    String line;    if (_ff.peek_line(line, errh) < 0)	return -1;    else if (!line || !isdigit(line[0]))	errh->lwarning(_ff.print_filename(), "first line suspicious; is this a tcpdump output file?");        _format_complaint = false;    if (output_is_push(0))	ScheduleInfo::initialize_task(this, &_task, _active, errh);    return 0;}voidFromTcpdump::cleanup(CleanupStage){    _ff.cleanup();}static voidappend_net_uint32_t(StringAccum &sa, uint32_t u){    sa << (char)(u >> 24) << (char)(u >> 16) << (char)(u >> 8) << (char)u;}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());    }}const char *FromTcpdump::read_tcp_line(WritablePacket *&q, const char *s, const char *end, int *data_len){    click_tcp *tcph = q->tcp_header();    // first, read flags    if (s < end && *s == '.')	tcph->th_flags = TH_ACK, s++;    else {	tcph->th_flags = 0;	while (s < end && IPSummaryDump::tcp_flag_mapping[(uint8_t) *s]) {	    tcph->th_flags |= (1 << (IPSummaryDump::tcp_flag_mapping[ (uint8_t) *s ] - 1));	    s++;	}    }    if (s >= end || *s != ' ')	return s;    // second, check for '[bad hdr length]' '[tcp sum ok]'    const char *s2;    if (s + 9 <= end && memcmp(s + 1, "[bad hdr", 8) == 0 && (s2 = find(s + 9, end, ']')) + 1 < end && s2[1] == ' ')	s = s2 + 1;    if (s + 14 <= end && memcmp(s + 1, "[tcp sum ok] ", 13) == 0)	s += 14;    else if (s + 9 <= end && memcmp(s + 1, "[bad tcp", 8) == 0 && (s2 = find(s + 9, end, ']')) + 1 < end && s2[1] == ' ')	s = s2 + 2;    else	s++;        // then read sequence numbers    uint32_t seq = 0, end_seq = 0, ack_seq = 0;    if (s < end && s[0] != 'a') {	const char *eseq = cp_unsigned(s, end, 0, &seq);	if (eseq == s || eseq >= end || *eseq != ':')	    return s;	const char *eend_seq = cp_unsigned(eseq + 1, end, 0, &end_seq);	if (eend_seq == eseq + 1 || eend_seq >= end || *eend_seq != '(')	    return s;	// skip parenthesized length	for (s = eend_seq + 1; s < end && isdigit(*s); s++)	    /* nada */;	if (s >= end || *s != ')')	    return s;	else if (s + 1 >= end || s[1] != ' ')	    return s + 1;	else	    s += 2;    }    *data_len = end_seq - seq;    // check for 'ack'    if (s + 4 < end && s[0] == 'a' && s[1] == 'c' && s[2] == 'k' && s[3] == ' ' && isdigit(s[4])) {	tcph->th_flags |= TH_ACK;	s = cp_unsigned(s + 4, end, 0, &ack_seq);	if (s < end && *s == ' ')	    s++;    }    // patch sequence numbers    FlowRecord *record = 0;    bool rev = false;    if (tcph->th_flags & TH_ACK) {	// first, look up a record for this flow	const click_ip *iph = q->ip_header();	rev = (tcph->th_sport < tcph->th_dport	       || (tcph->th_sport == tcph->th_dport && iph->ip_src.s_addr < iph->ip_dst.s_addr));	if (rev)	    record = _tcp_map.findp_force(IPFlowID(iph->ip_src, tcph->th_sport, iph->ip_dst, tcph->th_dport));	else	    record = _tcp_map.findp_force(IPFlowID(iph->ip_dst, tcph->th_dport, iph->ip_src, tcph->th_sport));	// use tcpdump's heuristic for deciding when this is a new flow	if ((!record->init_seq[0] && !record->init_seq[1]) || (tcph->th_flags & TH_SYN)) {	    record->init_seq[rev] = seq;	    record->init_seq[!rev] = ack_seq - 1;	} else {	    if (_absolute_seq < 0) // heuristic		_absolute_seq = (SEQ_GEQ(ack_seq, record->init_seq[!rev]) && ack_seq > 8000);	    if (seq == 0 && end_seq == 0)		seq = end_seq = record->last_seq[rev];	    else if (!_absolute_seq) {		seq += record->init_seq[rev];		end_seq += record->init_seq[rev];	    }	    if (!_absolute_seq)		ack_seq += record->init_seq[!rev];	}	// record last seen sequence numbers for assignment to pure acks	record->last_seq[rev] = end_seq + (tcph->th_flags & TH_SYN ? 1 : 0) + (tcph->th_flags & TH_FIN ? 1 : 0);	if (!record->last_seq[!rev])	    record->last_seq[!rev] = ack_seq;    }    tcph->th_seq = htonl(seq);    tcph->th_ack = htonl(ack_seq);        // check for 'win'    uint32_t u;    if (s + 4 < end && s[0] == 'w' && s[1] == 'i' && s[2] == 'n' && s[3] == ' ' && isdigit(s[4])) {	s = cp_unsigned(s + 4, end, 0, &u); // XXX check u <= 65535	tcph->th_win = htons(u);	if (s < end && *s == ' ')	    s++;    }    // check for 'urg'    if (s + 4 < end && s[0] == 'u' && s[1] == 'r' && s[2] == 'g' && s[3] == ' ' && isdigit(s[4])) {	s = cp_unsigned(s + 4, end, 0, &u); // XXX check u <= 65535	tcph->th_urp = htons(u);	if (s < end && *s != ' ')	    s++;    }    // check for options    StringAccum opt;    if (s < end && s[0] == '<') {	for (s++; s < end && *s != '>'; ) {	    int optlen1 = opt.length();	    if (s + 3 <= end && s[0] == 'n' && s[1] == 'o' && s[2] == 'p') {		opt << (char)TCPOPT_NOP;		s += 3;	    } else if (s + 3 <= end && s[0] == 'e' && s[1] == 'o' && s[2] == 'l') {		opt << (char)TCPOPT_EOL;		s += 3;	    } else if (s + 4 < end && s[0] == 'm' && s[1] == 's' && s[2] == 's' && s[3] == ' ' && isdigit(s[4])) {		s = cp_unsigned(s + 4, end, 0, &u); // XXX check u <= 65535		opt << (char)TCPOPT_MAXSEG << (char)TCPOLEN_MAXSEG << (char)((u >> 8) & 255) << (char)(u & 255);	    } else if (s + 7 < end && memcmp(s, "wscale ", 7) == 0 && isdigit(s[7])) {		s = cp_unsigned(s + 7, end, 0, &u); // XXX check u <= 255		opt << (char)TCPOPT_WSCALE << (char)TCPOLEN_WSCALE << (char)u;	    } else if (s + 6 <= end && memcmp(s, "sackOK", 6) == 0) {		opt << (char)TCPOPT_SACK_PERMITTED << (char)TCPOLEN_SACK_PERMITTED;		s += 6;	    } else if (s + 10 < end && memcmp(s, "timestamp ", 10) == 0 && isdigit(s[10])) {		s = cp_unsigned(s + 10, end, 0, &u);		if (s + 1 < end && *s == ' ' && isdigit(s[1])) {		    uint32_t u2;		    s = cp_unsigned(s + 1, end, 0, &u2);		    opt << (char)TCPOPT_TIMESTAMP << (char)TCPOLEN_TIMESTAMP;		    append_net_uint32_t(opt, u);		    append_net_uint32_t(opt, u2);		}	    } else if (s + 10 < end && memcmp(s, "sack sack ", 10) == 0 && isdigit(s[10])) {		uint32_t nsack, u2;		s = cp_unsigned(s + 10, end, 0, &nsack);		opt << (char)TCPOPT_SACK << (char)(nsack * 8 + 2);		while (s < end && *s == ' ')		    s++;		while (s + 1 < end && *s == '{' && isdigit(s[1])) {		    s = cp_unsigned(s + 1, end, 0, &u);		    if (s + 1 < end && *s == ':' && isdigit(s[1])) {			s = cp_unsigned(s + 1, end, 0, &u2);			if (s < end && *s == '}') {			    s++;			    if (record && !_absolute_seq) {				u += record->init_seq[!rev];				u2 += record->init_seq[!rev];			    }			    append_net_uint32_t(opt, u);			    append_net_uint32_t(opt, u2);			}		    }		}		while (s < end && *s == ' ')		    s++;	    }	    if (s < end && *s == ',')		s++;	    else if (s < end && *s != '>') { // not the option we thought		opt.set_length(optlen1);		while (s < end && *s != ',' && *s != '>')		    s++;	    }	}	if (s < end && *s == '>')	    s++;	while (opt.length() % 4 != 0)	    opt << (char)TCPOPT_EOL;	q = q->put(opt.length());	memcpy(q->transport_header() + sizeof(click_tcp), opt.data(), opt.length());	q->tcp_header()->th_off = (sizeof(click_tcp) + opt.length()) >> 2;    } else	tcph->th_off = sizeof(click_tcp) >> 2;    return s;}const char *FromTcpdump::read_udp_line(WritablePacket *&, const char *s, const char *end, int *data_len){    // first, check for '[bad hdr length]' '[udp sum ok]'    const char *s2;    if (s + 9 <= end && memcmp(s + 1, "[bad hdr", 8) == 0 && (s2 = find(s + 9, end, ']')) + 1 < end && s2[1] == ' ')	s = s2 + 1;    if (s + 14 <= end && memcmp(s + 1, "[udp sum ok] ", 13) == 0)	s += 14;

⌨️ 快捷键说明

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