diff --git a/fea/xrl_fea_target.cc b/fea/xrl_fea_target.cc index d9fe8cb..5c19e24 100644 --- a/fea/xrl_fea_target.cc +++ b/fea/xrl_fea_target.cc @@ -2285,7 +2285,7 @@ XrlFeaTarget::send_gratuitous_arps(const string& ifname, const Mac& mac, if (! addr->enabled()) continue; - ArpHeader::PAYLOAD data; + vector data; ArpHeader::make_gratuitous(data, mac, ip); XrlCmdError e = raw_link_0_1_send(ifname, vifname, mac, diff --git a/libproto/packet.cc b/libproto/packet.cc index c5a5784..5d74a8c 100644 --- a/libproto/packet.cc +++ b/libproto/packet.cc @@ -232,6 +232,7 @@ IpHeader4Writer::compute_checksum() set_ip_sum(ntohs(inet_checksum(data(), ip_header_len()))); } +#if 0 ArpHeader& ArpHeader::assign(uint8_t* data) { @@ -242,8 +243,10 @@ ArpHeader::assign(uint8_t* data) return *h; } + + const ArpHeader& -ArpHeader::assign(const PAYLOAD& payload) +ArpHeader::assign(const vector& payload) { const ArpHeader* h = reinterpret_cast(&payload[0]); @@ -259,6 +262,26 @@ ArpHeader::assign(const PAYLOAD& payload) return *h; } +#endif + +ArpHeader::ArpHeader() { + memset(this, 0, sizeof(this)); + ah_hw_len = 6; + ah_proto_len = 4; +} + +ArpHeader::ArpHeader(const vector& pkt) { + XLOG_ASSERT(pkt.size() <= sizeof(*this)); + memcpy(this, &pkt[0], pkt.size()); + if (ah_hw_len != 6) { + XLOG_WARNING("Bad arp header len: %i\n", (int)(ah_hw_len)); + ah_hw_len = 6; + } + if (ah_proto_len != 4) { + XLOG_WARNING("Bad arp proto len: %i\n", (int)(ah_proto_len)); + ah_proto_len = 4; + } +} bool ArpHeader::is_request() const @@ -277,13 +300,13 @@ ArpHeader::get_request() const IPv4 ip; - ip.copy_in(&ah_data[ah_hw_len * 2 + ah_proto_len]); + ip.copy_in(&ah_data_store[ah_hw_len * 2 + ah_proto_len]); return ip; } void -ArpHeader::make_reply(PAYLOAD& out, const Mac& mac) const +ArpHeader::make_reply(vector& out, const Mac& mac) const { // sanity checks if (!is_request()) @@ -293,35 +316,39 @@ ArpHeader::make_reply(PAYLOAD& out, const Mac& mac) const xorp_throw(BadPacketException, "Not an ethernet ARP"); // allocate size - int size = sizeof(*this) + ah_hw_len * 2 + ah_proto_len * 2; - out.reserve(size); - out.resize(size); + int sz = size(); + out.reserve(sz); + out.resize(sz); + + ArpHeader reply; - // copy request into reply - memcpy(&out[0], this, size); + // copy request (this) into reply + memcpy(&reply, this, sz); // make it a reply - ArpHeader& reply = const_cast(ArpHeader::assign(out)); reply.ah_op = htons(ARP_REPLY); // set the destination - size = ah_hw_len + ah_proto_len; - memcpy(&reply.ah_data[size], reply.ah_data, size); + sz = ah_hw_len + ah_proto_len; + memcpy(&reply.ah_data_store[sz], ah_data_store, sz); // set the source - mac.copy_out(reply.ah_data); - size += ah_hw_len; - memcpy(&reply.ah_data[ah_hw_len], &ah_data[size], ah_proto_len); + mac.copy_out(reply.ah_data_store); + sz += ah_hw_len; + memcpy(&reply.ah_data_store[ah_hw_len], &ah_data_store[sz], ah_proto_len); + + // Copy reply into 'out' vector. + memcpy(&out[0], &reply, reply.size()); } void ArpHeader::set_sender(const Mac& mac, const IPv4& ip) { ah_hw_fmt = htons(HW_ETHER); - ah_hw_len = mac.copy_out(ah_data); + ah_hw_len = mac.copy_out(ah_data_store); ah_proto_fmt = htons(ETHERTYPE_IP); - ah_proto_len = ip.copy_out(&ah_data[ah_hw_len]); + ah_proto_len = ip.copy_out(&ah_data_store[ah_hw_len]); } void @@ -332,7 +359,7 @@ ArpHeader::set_request(const IPv4& ip) ah_op = htons(ARP_REQUEST); - ip.copy_out(&ah_data[ah_hw_len * 2 + ah_proto_len]); + ip.copy_out(&ah_data_store[ah_hw_len * 2 + ah_proto_len]); } void @@ -345,27 +372,28 @@ ArpHeader::set_reply(const Mac& mac, const IPv4& ip) set_request(ip); ah_op = htons(ARP_REPLY); - mac.copy_out(&ah_data[ah_hw_len + ah_proto_len]); + mac.copy_out(&ah_data_store[ah_hw_len + ah_proto_len]); } uint32_t ArpHeader::size() const { - return sizeof(*this) + ah_hw_len * 2 + ah_proto_len * 2; + uint32_t rv = 8 + ah_hw_len * 2 + ah_proto_len * 2; + XLOG_ASSERT(rv <= sizeof(*this)); + return rv; } void -ArpHeader::make_gratuitous(PAYLOAD& data, const Mac& mac, const IPv4& ip) +ArpHeader::make_gratuitous(vector& data, const Mac& mac, const IPv4& ip) { - uint32_t sz = sizeof(ArpHeader) + 6 * 2 + 4 * 2; + ArpHeader arp; + uint32_t sz = arp.size(); data.resize(sz, 0); - ArpHeader& arp = ArpHeader::assign(&data[0]); - arp.set_sender(mac, ip); arp.set_request(ip); XLOG_ASSERT(arp.size() <= data.capacity()); - data.resize(arp.size()); + memcpy(&data[0], &arp, sz); } diff --git a/libproto/packet.hh b/libproto/packet.hh index ca8c54b..8b98ccd 100644 --- a/libproto/packet.hh +++ b/libproto/packet.hh @@ -914,9 +914,8 @@ public: /** * @short an ARP packet. */ -struct ArpHeader { - typedef vector PAYLOAD; - +class ArpHeader { +public: enum Op { ARP_REQUEST = 1, ARP_REPLY @@ -925,6 +924,9 @@ struct ArpHeader { HW_ETHER = 1 }; + ArpHeader(); + ArpHeader(const vector& pkt); + /** * Create an ARP packet. The caller must allocate memory and ensure enough * space (sizeof(ArpHeader) + (2 hw addresses) + (2 network addresses)). @@ -932,7 +934,7 @@ struct ArpHeader { * @return the ARP header. * @param data pointer where data should be stored. */ - static ArpHeader& assign(uint8_t* data); + //static ArpHeader& assign(uint8_t* data); /** * Parse an ARP packet. @@ -940,7 +942,7 @@ struct ArpHeader { * @return the ARP header. * @param payload the ARP header and data. */ - static const ArpHeader& assign(const PAYLOAD& payload); + //static const ArpHeader& assign(const vector& payload); /** * Create a gratuitous ARP. I.e., an ARP request for my own IP address - @@ -950,8 +952,8 @@ struct ArpHeader { * @param MAC address of IP. * @param ip IP address to create request for. */ - static void make_gratuitous(PAYLOAD& payload, const Mac& mac, - const IPv4& ip); + static void make_gratuitous(vector& payload, const Mac& mac, + const IPv4& ip); /** * Set the sender information in the ARP packet. @@ -1004,14 +1006,16 @@ struct ArpHeader { * @param out the ARP reply data (output parameter). * @param mac the MAC address of the requested IP address. */ - void make_reply(PAYLOAD& out, const Mac& mac) const; + void make_reply(vector& out, const Mac& mac) const; +private: uint16_t ah_hw_fmt; uint16_t ah_proto_fmt; uint8_t ah_hw_len; uint8_t ah_proto_len; uint16_t ah_op; - uint8_t ah_data[0]; -}; + uint8_t ah_data_store[6 * 2 + 4 * 2]; +} __attribute__((__packed__)); + #endif // __LIBPROTO_PACKET_HH__ diff --git a/vrrp/arpd.cc b/vrrp/arpd.cc index 51d2663..412b15a 100644 --- a/vrrp/arpd.cc +++ b/vrrp/arpd.cc @@ -116,7 +116,13 @@ ARPd::recv(const Mac& src, const PAYLOAD& payload) if (!_receiving) return; - const ArpHeader& ah = ArpHeader::assign(payload); + if (payload.size() > sizeof(ArpHeader)) { + XLOG_ERROR("ERROR: payload_size: %i is > than ArpHeader size: %i\n", + (int)(payload.size()), (int)(sizeof(ArpHeader))); + return; + } + + ArpHeader ah(payload); if (!ah.is_request()) return;