I have actually made an ARPSniffer element which takes an ARPTable and
updates it, and I pass all ARPRequests through the ARPSniffer before they go
to my ARPResponder.

A change that might be good to make would be to make ARPSniffer only update
(not insert into) the ARPTable, so that on extremely large subnets, it would
be less likely to run out of ARPTable entries...

I've attached the element that I made.  It could definitely use some more
documentation/ description of how it should be used.

Is this the right interface do you think?  Do you think that the update-only
functionality is important?

Cliff

On Tue, Apr 6, 2010 at 6:54 AM, Lars Bro <[email protected]> wrote:

> Hi, List
>
> My router sends packets to an IP address that may be hosted by one of
> several possible remote systems. In order to support that this address is
> switched between these hosts, I use TIMEOUT 1 as argument for the
> ARPRequester.
>
> Now I have been told that it is normal that when a new system takes over,
> it
> does some ARP requests (what it asks for does as far as I can see not
> matter
> at all)  with this address as the TELL part, assuming that everybody will
> then record that as the new holder of the address.
>
> is it really so?
>
> Would it be possible then, to filter incoming ARP requests for those with
> the "shared" IP address in the TELL part, and send them not just to the
> ARPResponder but also to the ARPRequester ? I guess that I need to make an
> element that makes an "unsolicited" ARP response out of an ARP request.,
> then.
>
> Will the ARPRequester react correctly to "unsolicited" responses? or will
> it
> throw these away?
>
> Is this function already implemented, or would it be of general interest to
> the community if I post an implementation?
>
> yours,
> Lars Bro
> _______________________________________________
> click mailing list
> [email protected]
> https://amsterdam.lcs.mit.edu/mailman/listinfo/click
>
#ifndef CLICK_ARPSNIFFER_HH
#define CLICK_ARPSNIFFER_HH
#include <click/element.hh>
CLICK_DECLS

/*
=c

ARPSniffer(ARP_TABLE)

=s arp

Adds the sender information from ARP packets into ARP_TABLE

=a

ARPQuerier, ARPTable
*/

class ARPSniffer : public Element { public:

    ARPSniffer();
    ~ARPSniffer();

    const char *class_name() const		{ return "ARPSniffer"; }
    const char *port_count() const		{ return PORTS_1_1; }
    const char *processing() const		{ return AGNOSTIC; }

    int configure(Vector<String> &, ErrorHandler *);
    bool can_live_reconfigure() const		{ return true; }
    void add_handlers();

    Packet *simple_action(Packet *p);

  private:

    class ARPTable *_arpt;
    uint32_t _count;
    bool _debug;
};

CLICK_ENDDECLS
#endif
/*
 * arpsniffer.{cc,hh} -- sniffs ARP sender info
 * Cliff Frey
 *
 * Copyright (c) 2009 Meraki, 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 "arpsniffer.hh"
#include <clicknet/ether.h>
#include <click/etheraddress.hh>
#include <click/ipaddress.hh>
#include <click/confparse.hh>
#include <click/error.hh>
#include <click/glue.hh>
#include "arptable.hh"
CLICK_DECLS

ARPSniffer::ARPSniffer()
{
}

ARPSniffer::~ARPSniffer()
{
}

int
ARPSniffer::configure(Vector<String> &conf, ErrorHandler *errh)
{
    _count = 0;
    _debug = false;
    if (cp_va_kparse(conf, this, errh,
		     "TABLE", cpkP+cpkM, cpElementCast, "ARPTable", &_arpt,
		     "DEBUG", 0, cpBool, &_debug,
		     cpEnd) < 0)
	return -1;
    return 0;
}

Packet *
ARPSniffer::simple_action(Packet *p)
{
    if (p->length() < sizeof(click_ether) + sizeof(click_ether_arp))
	return p;

    click_ether *ethh = (click_ether *) p->data();
    click_ether_arp *arph = (click_ether_arp *) (ethh + 1);
    IPAddress spa = IPAddress(arph->arp_spa);
    EtherAddress sha = EtherAddress(arph->arp_sha);
    if (ethh->ether_type != htons(ETHERTYPE_ARP)
	|| arph->ea_hdr.ar_hrd != htons(ARPHRD_ETHER)
	|| arph->ea_hdr.ar_pro != htons(ETHERTYPE_IP)
	|| sha.is_group()
	|| spa.is_multicast() )
	return p;

    _count++;
    if (_debug)
	click_chatter("%{element} adding %{ip_ptr} %{ether_ptr}\n", this, &spa, &sha);
    _arpt->insert(spa, sha);
    return p;
}

void
ARPSniffer::add_handlers()
{
    add_data_handlers("debug", Handler::OP_READ | Handler::OP_WRITE | Handler::CHECKBOX, &_debug);
    add_data_handlers("count", Handler::OP_READ | Handler::OP_WRITE, &_count);
}

CLICK_ENDDECLS
EXPORT_ELEMENT(ARPSniffer)
ELEMENT_REQUIRES(ARPTable)
ELEMENT_MT_SAFE(ARPSniffer)
_______________________________________________
click mailing list
[email protected]
https://amsterdam.lcs.mit.edu/mailman/listinfo/click

Reply via email to