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

Reply via email to