Dear list,
Attached you will find an element our students (Jens De Wit and Nico Van Looy)
produced while working on their FireSim project, the Firewall Simulation in
Click as presented on SyClick.
The element allows transmitting ICMP packets with all types of codes and types,
which makes this element more general than ICMPPingEncap. It is a bit the ICMP
alternative to UDPIPEncap.
The element code is largely based on ICMPPingEncap so Jens and Nico suggested
just patching ICMPPingEncap with the new behaviour, although of course the name
then does not cover the contents of the element.
Jens promised to write a unit test with the testie framework, so this can be
expected as well.
best regards,
Bart
#ifndef CLICK_ICMPIPENCAP_HH
#define CLICK_ICMPIPENCAP_HH
#include <click/element.hh>
#include <click/timer.hh>
CLICK_DECLS
class ICMPIPEncap : public Element { public:
ICMPIPEncap();
~ICMPIPEncap();
const char *class_name() const { return "ICMPIPEncap"; }
const char *port_count() const { return PORTS_1_1; }
const char *processing() const { return AGNOSTIC; }
const char *flags() const { return "A"; }
int configure(Vector<String> &, ErrorHandler *);
void add_handlers();
Packet *simple_action(Packet *);
private:
struct in_addr _src;
struct in_addr _dst;
uint16_t _icmp_id;
uint16_t _ip_id;
uint8_t _icmp_type;
uint8_t _icmp_code;
#if HAVE_FAST_CHECKSUM && FAST_CHECKSUM_ALIGNED
bool _aligned;
#endif
static String read_handler(Element *, void *);
static int write_handler(const String &, Element *, void *, ErrorHandler *);
};
CLICK_ENDDECLS
#endif
#include <click/config.h>
#include "icmpipencap.hh"
#include <click/confparse.hh>
#include <click/error.hh>
#include <clicknet/ip.h>
#include <clicknet/icmp.h>
#include <click/packet_anno.hh>
#include <click/standard/alignmentinfo.hh>
CLICK_DECLS
ICMPIPEncap::ICMPIPEncap()
: _icmp_id(0), _ip_id(1), _icmp_type(0), _icmp_code(0)
{
}
ICMPIPEncap::~ICMPIPEncap()
{
}
int
ICMPIPEncap::configure(Vector<String> &conf, ErrorHandler *errh)
{
if (cp_va_kparse(conf, this, errh,
"SRC", cpkP+cpkM, cpIPAddress, &_src,
"DST", cpkP+cpkM, cpIPAddress, &_dst,
"TYPE", cpkP+cpkM, cpUnsignedShort, &_icmp_type,
"CODE", cpkP, cpUnsignedShort, &_icmp_code,
"IDENTIFIER", 0, cpUnsignedShort, &_icmp_id,
cpEnd) < 0)
return -1;
#if HAVE_FAST_CHECKSUM && FAST_CHECKSUM_ALIGNED
{ // check alignment
int ans, c, o;
ans = AlignmentInfo::query(this, 0, c, o);
_aligned = (ans && c == 4 && o == 0);
if (!_aligned)
errh->warning("IP header unaligned, cannot use fast IP checksum");
if (!ans)
errh->message("(Try passing the configuration through `click-align'.)");
}
#endif
return 0;
}
Packet *
ICMPIPEncap::simple_action(Packet *p)
{
if (WritablePacket *q = p->push(sizeof(click_ip) + sizeof(struct click_icmp_echo))) {
click_ip *ip = reinterpret_cast<click_ip *>(q->data());
ip->ip_v = 4;
ip->ip_hl = sizeof(click_ip) >> 2;
ip->ip_tos = 0;
ip->ip_len = htons(q->length());
ip->ip_id = htons(_ip_id);
ip->ip_off = 0;
ip->ip_ttl = 255;
ip->ip_p = IP_PROTO_ICMP; /* icmp */
ip->ip_sum = 0;
ip->ip_src = _src;
ip->ip_dst = _dst;
click_icmp_echo *icmp = (struct click_icmp_echo *) (ip + 1);
icmp->icmp_type = _icmp_type;
icmp->icmp_code = _icmp_code;
icmp->icmp_cksum = 0;
#ifdef __linux__
icmp->icmp_identifier = _icmp_id;
icmp->icmp_sequence = _ip_id;
#else
icmp->icmp_identifier = htons(_icmp_id);
icmp->icmp_sequence = htons(_ip_id);
#endif
#if HAVE_FAST_CHECKSUM && FAST_CHECKSUM_ALIGNED
if (_aligned)
ip->ip_sum = ip_fast_csum((unsigned char *)ip, sizeof(click_ip) >> 2);
else
ip->ip_sum = click_in_cksum((unsigned char *)ip, sizeof(click_ip));
#elif HAVE_FAST_CHECKSUM
ip->ip_sum = ip_fast_csum((unsigned char *)ip, sizeof(click_ip) >> 2);
#else
ip->ip_sum = click_in_cksum((unsigned char *)ip, sizeof(click_ip));
#endif
icmp->icmp_cksum = click_in_cksum((const unsigned char *)icmp, q->length() - sizeof(click_ip));
q->set_dst_ip_anno(IPAddress(_dst));
q->set_ip_header(ip, sizeof(click_ip));
_ip_id += (_ip_id == 0xFFFF ? 2 : 1);
return q;
} else
return 0;
}
String ICMPIPEncap::read_handler(Element *e, void *thunk)
{
ICMPIPEncap *i = static_cast<ICMPIPEncap *>(e);
if (thunk)
return IPAddress(i->_dst).unparse();
else
return IPAddress(i->_src).unparse();
}
int ICMPIPEncap::write_handler(const String &str, Element *e, void *thunk, ErrorHandler *errh)
{
ICMPIPEncap *i = static_cast<ICMPIPEncap *>(e);
IPAddress a;
if (!cp_ip_address(str, &a))
return errh->error("expected IP address");
if (thunk)
i->_dst = a;
else
i->_src = a;
return 0;
}
void ICMPIPEncap::add_handlers()
{
add_read_handler("src", read_handler, (void *) 0, Handler::CALM);
add_write_handler("src", write_handler, (void *) 0);
add_read_handler("dst", read_handler, (void *) 1, Handler::CALM);
add_write_handler("dst", write_handler, (void *) 1);
}
CLICK_ENDDECLS
EXPORT_ELEMENT(ICMPIPEncap)
_______________________________________________
click mailing list
[email protected]
https://amsterdam.lcs.mit.edu/mailman/listinfo/click