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

📄 iprw.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
📖 第 1 页 / 共 2 页
字号:
// -*- mode: c++; c-basic-offset: 4 -*-/* * iprw.{cc,hh} -- rewrites packet source and destination * Max Poletto, Eddie Kohler * * Copyright (c) 2000 Massachusetts Institute of Technology * Copyright (c) 2001 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 "iprw.hh"#include "elements/ip/iprwpatterns.hh"#include <clicknet/ip.h>#include <clicknet/tcp.h>#include <clicknet/udp.h>#include <click/confparse.hh>#include <click/straccum.hh>#include <click/error.hh>#ifdef CLICK_LINUXMODULE#include <click/cxxprotect.h>CLICK_CXX_PROTECT#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)# include <asm/softirq.h>#endif#include <net/sock.h>CLICK_CXX_UNPROTECT#include <click/cxxunprotect.h>#endifCLICK_DECLS//// IPRw::Mapping//IPRw::Mapping::Mapping(bool dst_anno)  : _flags(dst_anno ? F_DST_ANNO : 0), _ip_p(0), _pat(0), _free_next(0){}voidIPRw::Mapping::initialize(int ip_p, const IPFlowID &in, const IPFlowID &out,			  int output, uint16_t flags, Mapping *reverse){    // set fields    _ip_p = ip_p;    _mapto = out;    _output = output;    assert(output >= 0 && output < 256);    _flags |= flags;    _reverse = reverse;      // set checksum deltas    const unsigned short* source_words = (const unsigned short*)&in;    const unsigned short* dest_words = (const unsigned short*)&_mapto;    unsigned delta = 0;    for (int i = 0; i < 4; i++) {	delta += ~source_words[i] & 0xFFFF;	delta += dest_words[i];    }    delta = (delta & 0xFFFF) + (delta >> 16);    _ip_csum_delta = delta + (delta >> 16);      for (int i = 4; i < 6; i++) {	delta += ~source_words[i] & 0xFFFF;	delta += dest_words[i];    }    delta = (delta & 0xFFFF) + (delta >> 16);    _udp_csum_delta = delta + (delta >> 16);}voidIPRw::Mapping::make_pair(int ip_p, const IPFlowID &inf, const IPFlowID &outf,			 int foutput, int routput,			 Mapping *in_map, Mapping *out_map){    in_map->initialize(ip_p, inf, outf, foutput, 0, out_map);    out_map->initialize(ip_p, outf.rev(), inf.rev(), routput, F_REVERSE, in_map);}voidIPRw::Mapping::apply(WritablePacket *p){    click_ip *iph = p->ip_header();    assert(iph);      // IP header    iph->ip_src = _mapto.saddr();    iph->ip_dst = _mapto.daddr();    if (_flags & F_DST_ANNO)	p->set_dst_ip_anno(_mapto.daddr());    unsigned sum = (~iph->ip_sum & 0xFFFF) + _ip_csum_delta;    sum = (sum & 0xFFFF) + (sum >> 16);    iph->ip_sum = ~(sum + (sum >> 16));    mark_used();    // end if not first fragment    if (!IP_FIRSTFRAG(iph))	return;      // UDP/TCP header    if (_ip_p == IP_PROTO_TCP) {    	click_tcp *tcph = p->tcp_header();	tcph->th_sport = _mapto.sport();	tcph->th_dport = _mapto.dport();	unsigned sum2 = (~tcph->th_sum & 0xFFFF) + _udp_csum_delta;	sum2 = (sum2 & 0xFFFF) + (sum2 >> 16);	tcph->th_sum = ~(sum2 + (sum2 >> 16));    	// check for session ending flags	if (tcph->th_flags & TH_RST)	    set_session_over();	else if (tcph->th_flags & TH_FIN)	    set_session_flow_over();	else if (tcph->th_flags & TH_SYN)	    clear_session_flow_over();	    } else if (_ip_p == IP_PROTO_UDP) {    	click_udp *udph = p->udp_header();	udph->uh_sport = _mapto.sport();	udph->uh_dport = _mapto.dport();	if (udph->uh_sum) {	// 0 checksum is no checksum	    unsigned sum2 = (~udph->uh_sum & 0xFFFF) + _udp_csum_delta;	    sum2 = (sum2 & 0xFFFF) + (sum2 >> 16);	    udph->uh_sum = ~(sum2 + (sum2 >> 16));	}        }}StringIPRw::Mapping::unparse() const{    return reverse()->flow_id().rev().unparse() + " => " + flow_id().unparse() + " [" + String(output()) + "]";}//// IPRw::Pattern//IPRw::Pattern::Pattern(const IPAddress &saddr, int sport,		       const IPAddress &daddr, int dport,		       bool is_napt, bool sequential, uint32_t variation_top)    : _saddr(saddr), _sport(sport), _daddr(daddr), _dport(dport),      _variation_top(variation_top), _next_variation(0), _is_napt(is_napt),      _sequential(sequential), _refcount(0), _nmappings(0){    if (_variation_top > 0)	for (_variation_mask = 1; _variation_mask < _variation_top; )	    _variation_mask = (_variation_mask << 1) | 1;}namespace {enum { PE_NAPT, PE_NAT, PE_SADDR, PE_SPORT, PE_DADDR, PE_DPORT };static const char* const pe_messages[] = {    "syntax error, expected 'SADDR SPORT[-SPORTH] DADDR DPORT'",    "syntax error, expected 'SADDR[-SADDRH] DADDR'",    "bad source address",    "bad source port",    "bad destination address",    "bad destination port"};static inline intpattern_error(int what, ErrorHandler* errh){    return errh->error(pe_messages[what]);}}intIPRw::Pattern::parse_napt(Vector<String> &words, Pattern **pstore,			  Element *e, ErrorHandler *errh){    if (words.size() != 4)	return pattern_error(PE_NAPT, errh);      IPAddress saddr, daddr;    int32_t sportl, sporth, dport;    bool sequential = false;      if (words[0] == "-")	saddr = 0;    else if (!cp_ip_address(words[0], &saddr, e))	return pattern_error(PE_SADDR, errh);      if (words[1] == "-")	sportl = sporth = 0;    else {	const char* end = words[1].end();	if (end > words[1].begin() && end[-1] == '#')	    sequential = true, end--;	const char* dash = find(words[1].begin(), end, '-');	if (!(cp_integer(words[1].substring(words[1].begin(), dash), &sportl)	      && sportl > 0 && sportl <= 0xFFFF	      && (dash == end ? (sporth = sportl)		  : (cp_integer(words[1].substring(dash + 1, end), &sporth)		     && sporth >= sportl && sporth <= 0xFFFF))))	    return pattern_error(PE_SPORT, errh);    }    if (words[2] == "-")	daddr = 0;    else if (!cp_ip_address(words[2], &daddr, e))	return pattern_error(PE_DADDR, errh);      if (words[3] == "-")	dport = 0;    else if (!cp_integer(words[3], &dport) || dport <= 0 || dport > 0xFFFF)	return pattern_error(PE_DPORT, errh);    *pstore = new Pattern(saddr, htons(sportl), daddr, htons(dport), true, sequential, sporth - sportl);    return 0;}intIPRw::Pattern::parse_nat(Vector<String> &words, Pattern **pstore,			 Element *e, ErrorHandler *errh){    if (words.size() != 1 && words.size() != 2)	return pattern_error(PE_NAT, errh);      IPAddress saddr1, saddr2;    bool sequential = false;    if (words[0] == "-")	saddr1 = saddr2 = 0;    else {	const char* end = words[0].end();	if (end > words[0].begin() && end[-1] == '#')	    sequential = true, end--;	const char* dash = find(words[0].begin(), end, '-');	if (dash == end) {	    if (!cp_ip_prefix(words[0].substring(words[0].begin(), end), &saddr1, &saddr2, true, e) || !saddr1 || !saddr2)		return pattern_error(PE_SADDR, errh);	    if (saddr2 == IPAddress(0xFFFFFFFFU))		saddr2 = saddr1;	    else if (saddr2 == IPAddress(htonl(0xFFFFFFFEU))) {		saddr1 &= saddr2;		saddr2 = saddr1 | IPAddress(htonl(0x00000001U));	    } else {		uint32_t s1 = saddr1 & saddr2;		uint32_t s2 = saddr1 | ~saddr2;		// don't count PREFIX.0 and PREFIX.255		saddr1 = htonl(ntohl(s1) + 1);		saddr2 = htonl(ntohl(s2) - 1);	    }	} else if (!cp_ip_address(words[0].substring(words[0].begin(), dash), &saddr1, e)		   || !cp_ip_address(words[0].substring(dash+1, end), &saddr2, e)		   || ntohl(saddr1.addr()) > ntohl(saddr2.addr()))	    return pattern_error(PE_SADDR, errh);    }    IPAddress daddr;    if (words.size() == 1 || words[1] == "-")	daddr = 0;    else if (!cp_ip_address(words[1], &daddr, e) || !daddr)	return pattern_error(PE_DADDR, errh);        *pstore = new Pattern(saddr1, 0, daddr, 0, false, sequential, ntohl(saddr2.addr()) - ntohl(saddr1.addr()));    return 0;}intIPRw::Pattern::parse(const String &conf, Pattern **pstore,		     Element *e, ErrorHandler *errh){    Vector<String> words;    cp_spacevec(conf, words);    // check for IPRewriterPatterns reference    if (words.size() == 1) {	String name = cp_unquote(words[0]);	if (Pattern *p = IPRewriterPatterns::find(e, name, errh)) {	    *pstore = p;	    return 0;	} else	    return -1;    } else if (words.size() == 2)	return parse_nat(words, pstore, e, errh);    else	return parse_napt(words, pstore, e, errh);}intIPRw::Pattern::parse_with_ports(const String &conf, Pattern **pstore,				int *fport_store, int *rport_store,				Element *e, ErrorHandler *errh){    Vector<String> words;    cp_spacevec(conf, words);    int32_t fport, rport;    if (words.size() <= 2	|| !cp_integer(words[words.size() - 2], &fport)	|| !cp_integer(words[words.size() - 1], &rport)	|| fport < 0 || rport < 0)	return errh->error("bad forward and/or reverse ports in pattern spec");    words.resize(words.size() - 2);    // check for IPRewriterPatterns reference    Pattern *p;    if (parse(cp_unspacevec(words), &p, e, errh) >= 0) {	*pstore = p;	*fport_store = fport;	*rport_store = rport;	return 0;    } else	return -1;}boolIPRw::Pattern::can_accept_from(const Pattern &o) const{    if (_daddr != o._daddr || _dport != o._dport || _is_napt != o._is_napt	|| (_is_napt ? _saddr != o._saddr : _sport != o._sport))	return false;    uint32_t low, o_low;    if (_is_napt)	low = ntohs(_sport), o_low = ntohs(o._sport);    else	low = ntohl(_saddr.addr()), o_low = ntohl(o._saddr.addr());    uint32_t high = low + _variation_top;    uint32_t o_high = o_low + _variation_top;    return low <= o_low && o_high <= high;}boolIPRw::Pattern::create_mapping(int ip_p, const IPFlowID& in,			      int fport, int rport,			      Mapping* fmap, Mapping* rmap,			      const Map& rev_map){    IPFlowID out(in);    if (_saddr)	out.set_saddr(_saddr);    if (_sport)	out.set_sport(_sport);    if (_daddr)	out.set_daddr(_daddr);    if (_dport)	out.set_dport(_dport);    if (_variation_top) {

⌨️ 快捷键说明

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