Skip to content

Commit

Permalink
StoreIPAddress: Refactor, improve 64-bit compatibility, add test.
Browse files Browse the repository at this point in the history
Inspired by a patch from Harold Schiöberg.
  • Loading branch information
kohler committed Nov 15, 2009
1 parent d16ca89 commit e02d652
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 13 deletions.
33 changes: 21 additions & 12 deletions elements/ip/storeipaddress.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,26 @@ StoreIPAddress::~StoreIPAddress()
int
StoreIPAddress::configure(Vector<String> &conf, ErrorHandler *errh)
{
if (conf.size() < 1 || conf.size() > 2)
return errh->error("expected [IP address, ] byte offset");
_use_address = (conf.size() == 2);
if (_use_address && !cp_ip_address(conf[0], &_address))
return errh->error("first argument should be IP address");
if (conf.back().lower() == "src")
_offset = (unsigned) -12;
String offset;
int r;
_use_address = false;
if (conf.size() == 1)
r = cp_va_kparse(conf, this, errh,
"OFFSET", cpkP+cpkM, cpWord, &offset,
cpEnd);
else
r = cp_va_kparse(conf, this, errh,
"ADDR", cpkP+cpkC+cpkM, &_use_address, cpIPAddress, &_address,
"OFFSET", cpkP+cpkM, cpWord, &offset,
cpEnd);
if (r < 0)
return r;
if (offset.lower() == "src")
_offset = -12;
else if (conf.back().lower() == "dst")
_offset = (unsigned) -16;
else if (!cp_integer(conf.back(), &_offset))
return errh->error("last argument should be byte offset of IP address");
_offset = -16;
else if (!cp_integer(conf.back(), &_offset) || _offset < 0)
return errh->error("type mismatch: OFFSET requires integer");
return 0;
}

Expand All @@ -56,14 +65,14 @@ StoreIPAddress::simple_action(Packet *p)
{
// XXX error reporting?
IPAddress ipa = (_use_address ? _address : p->dst_ip_anno());
if ((ipa || _use_address) && _offset + 4 <= p->length()) {
if ((ipa || _use_address) && (uint32_t) _offset + 4 <= p->length()) {
if (WritablePacket *q = p->uniqueify()) {
memcpy(q->data() + _offset, &ipa, 4);
return q;
} else
return 0;

} else if (_offset >= (unsigned) -16 && p->has_network_header()
} else if (_offset >= -16 && p->has_network_header()
&& p->ip_header_length() >= sizeof(click_ip)) {
// special case: store IP address into IP header
// and update checksums incrementally
Expand Down
2 changes: 1 addition & 1 deletion elements/ip/storeipaddress.hh
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class StoreIPAddress : public Element { public:

private:

unsigned _offset;
int _offset;
IPAddress _address;
bool _use_address;

Expand Down
26 changes: 26 additions & 0 deletions test/ip/StoreIPAddress-01.testie
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
%script
click C

%file C
InfiniteSource(LIMIT 6, STOP true, DATA \<99999999 99999999 99999999 99999999 99999999>)
-> MarkIPHeader(0)
-> SetIPAddress(1.0.0.2)
-> r :: RoundRobinSwitch
-> Print(a)
-> d :: Discard;
r[1] -> StoreIPAddress(0) -> Print(b) -> d;
r[2] -> StoreIPAddress(1.0.0.3, 4) -> Print(c) -> d;
r[3] -> StoreIPAddress(src) -> Print(d) -> d;
r[4] -> StoreIPAddress(dst) -> Print(e) -> d;
r[5] -> StoreIPAddress(1.0.0.4, dst) -> Print(f) -> d;

%expect stderr
a: 20 | 99999999 99999999 99999999 99999999 99999999
b: 20 | 01000002 99999999 99999999 99999999 99999999
c: 20 | 99999999 01000003 99999999 99999999 99999999
d: 20 | 99999999 99999999 9999cbca 01000002 99999999
e: 20 | 99999999 99999999 9999cbca 99999999 01000002
f: 20 | 99999999 99999999 9999cbc8 99999999 01000004

%ignore
expensive{{.*}}

0 comments on commit e02d652

Please sign in to comment.