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

📄 icmprewriter.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
字号:
/* -*- c-basic-offset: 2 -*- *//* * icmprewriter.{cc,hh} -- rewrites ICMP non-echoes and non-replies * Eddie Kohler * * Copyright (c) 2000 Mazu Networks, 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 "icmprewriter.hh"#include <clicknet/icmp.h>#include <click/confparse.hh>#include <click/straccum.hh>#include <click/error.hh>CLICK_DECLSICMPRewriter::ICMPRewriter()  : Element(1, 1){}ICMPRewriter::~ICMPRewriter(){}voidICMPRewriter::notify_noutputs(int n){  set_noutputs(n < 2 ? 1 : 2);}intICMPRewriter::configure(Vector<String> &conf, ErrorHandler *errh){  String arg;  if (cp_va_parse(conf, this, errh,		  cpArgument, "rewriters", &arg,		  cpEnd) < 0)    return -1;  Vector<String> words;  cp_spacevec(arg, words);  for (int i = 0; i < words.size(); i++) {    if (Element *e = cp_element(words[i], this, errh)) {      if (IPRw *rw = static_cast<IPRw *>(e->cast("IPRw")))	_maps.push_back(rw);      else if (ICMPPingRewriter *rw = static_cast<ICMPPingRewriter *>(e->cast("ICMPPingRewriter")))	_ping_maps.push_back(rw);      else	errh->error("element `%s' is not an IP rewriter", words[i].cc());    }  }  if (_maps.size() == 0 && _ping_maps.size() == 0)    return errh->error("no IP rewriters supplied");  return 0;}voidICMPRewriter::rewrite_packet(WritablePacket *p, click_ip *embedded_iph,			     click_udp *embedded_udph, const IPFlowID &flow,			     IPRw::Mapping *mapping){  click_ip *iph = p->ip_header();  click_icmp *icmph = p->icmp_header();  // XXX incremental checksums?    IPFlowID new_flow = mapping->flow_id().rev();    // change IP header destination if appropriate  if (IPAddress(iph->ip_dst) == flow.saddr()) {    unsigned hlen = iph->ip_hl << 2;    iph->ip_dst = new_flow.saddr();    iph->ip_sum = 0;    iph->ip_sum = click_in_cksum((unsigned char *)iph, hlen);  }    // don't bother patching embedded IP or UDP checksums  embedded_iph->ip_src = new_flow.saddr();  embedded_iph->ip_dst = new_flow.daddr();  embedded_udph->uh_sport = new_flow.sport();  embedded_udph->uh_dport = new_flow.dport();  // but must patch ICMP checksum  icmph->icmp_cksum = 0;  icmph->icmp_cksum = click_in_cksum((unsigned char *)icmph, p->length() - p->transport_header_offset());}voidICMPRewriter::rewrite_ping_packet(WritablePacket *p, click_ip *embedded_iph,				  click_icmp_echo *embedded_icmph, const IPFlowID &flow,				  ICMPPingRewriter::Mapping *mapping){  click_ip *iph = p->ip_header();  click_icmp *icmph = p->icmp_header();  // XXX incremental checksums?    IPFlowID new_flow = mapping->flow_id().rev();    // change IP header destination if appropriate  if (IPAddress(iph->ip_dst) == flow.saddr()) {    unsigned hlen = iph->ip_hl << 2;    iph->ip_dst = new_flow.saddr();    iph->ip_sum = 0;    iph->ip_sum = click_in_cksum((unsigned char *)iph, hlen);  }    // don't bother patching embedded ICMP checksum  embedded_iph->ip_src = new_flow.saddr();  embedded_iph->ip_dst = new_flow.daddr();  embedded_icmph->icmp_identifier = new_flow.sport();  // but must patch ICMP checksum  icmph->icmp_cksum = 0;  icmph->icmp_cksum = click_in_cksum((unsigned char *)icmph, p->length() - p->transport_header_offset());}Packet *ICMPRewriter::simple_action(Packet *p_in){  WritablePacket *p = p_in->uniqueify();  if (!p)    return 0;  else if (p->ip_header()->ip_p != IP_PROTO_ICMP) {    p->kill();    return 0;  }    click_icmp *icmph = p->icmp_header();  switch (icmph->icmp_type) {   case ICMP_UNREACH:   case ICMP_TIMXCEED:   case ICMP_PARAMPROB:   case ICMP_SOURCEQUENCH:   case ICMP_REDIRECT: {     // check length of embedded IP header     click_ip *embedded_iph = reinterpret_cast<click_ip *>(icmph + 1);     unsigned hlen = embedded_iph->ip_hl << 2;     if (p->transport_length() < (int)(sizeof(click_icmp) + hlen + 8)	 || hlen < sizeof(click_ip))       goto bad;     // check protocol     int embedded_p = embedded_iph->ip_p;     if (embedded_p == IP_PROTO_UDP || embedded_p == IP_PROTO_TCP) {       // TCP or UDP       // create flow ID       click_udp *embedded_udph = reinterpret_cast<click_udp *>(reinterpret_cast<unsigned char *>(embedded_iph) + hlen);       IPFlowID flow(embedded_iph->ip_src, embedded_udph->uh_sport, embedded_iph->ip_dst, embedded_udph->uh_dport);            IPRw::Mapping *mapping = 0;       for (int i = 0; i < _maps.size() && !mapping; i++)	 mapping = _maps[i]->get_mapping(embedded_p, flow.rev());       if (!mapping)	 goto unmapped;            rewrite_packet(p, embedded_iph, embedded_udph, flow, mapping);            } else if (embedded_p == IP_PROTO_ICMP) {       // ICMP       click_icmp_sequenced *embedded_icmph = reinterpret_cast<click_icmp_sequenced *>(reinterpret_cast<unsigned char *>(embedded_iph) + hlen);              int embedded_type = embedded_icmph->icmp_type;       if (embedded_type != ICMP_ECHO && embedded_type != ICMP_ECHOREPLY)	 goto unmapped;       bool ask_for_request = (embedded_type != ICMP_ECHO);              IPFlowID flow(embedded_iph->ip_src, embedded_icmph->icmp_identifier, embedded_iph->ip_dst, embedded_icmph->icmp_identifier);       ICMPPingRewriter::Mapping *mapping = 0;       for (int i = 0; i < _ping_maps.size() && !mapping; i++)	 mapping = _ping_maps[i]->get_mapping(ask_for_request, flow.rev());       if (!mapping)	 goto unmapped;       rewrite_ping_packet(p, embedded_iph, embedded_icmph, flow, mapping);            } else       goto unmapped;            return p;   }   bad:    p->kill();    return 0;   unmapped:   default:    checked_output_push(1, p);    return 0;  }}CLICK_ENDDECLSELEMENT_REQUIRES(IPRw ICMPPingRewriter)EXPORT_ELEMENT(ICMPRewriter)

⌨️ 快捷键说明

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