diff --git a/elements/ip/storeipaddress.cc b/elements/ip/storeipaddress.cc index 9176b5bf56..8f5fa5253f 100644 --- a/elements/ip/storeipaddress.cc +++ b/elements/ip/storeipaddress.cc @@ -37,17 +37,26 @@ StoreIPAddress::~StoreIPAddress() int StoreIPAddress::configure(Vector &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; } @@ -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 diff --git a/elements/ip/storeipaddress.hh b/elements/ip/storeipaddress.hh index 11eda21dc6..72edf9417f 100644 --- a/elements/ip/storeipaddress.hh +++ b/elements/ip/storeipaddress.hh @@ -66,7 +66,7 @@ class StoreIPAddress : public Element { public: private: - unsigned _offset; + int _offset; IPAddress _address; bool _use_address; diff --git a/test/ip/StoreIPAddress-01.testie b/test/ip/StoreIPAddress-01.testie new file mode 100644 index 0000000000..11d9873d70 --- /dev/null +++ b/test/ip/StoreIPAddress-01.testie @@ -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{{.*}}