Skip to content

Commit 0498aef

Browse files
committed
network: (fixes #1268) remove address type-0 as a wildcard and disallow Address type-0
1 parent 2e9eb18 commit 0498aef

17 files changed

+328
-225
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ This file is a best-effort approach to solving this issue; we will do our best b
2020

2121
### Changes to existing API
2222

23+
* Address type 0 was previously used as a wildcard. Type 0 is now disallowd for any practical use. In order to create an Address from raw bytes, you must now set the Address type beforehand. An example is in ArpHeader::Deserialize.
24+
2325
### Changes to build system
2426

2527
### Changed behavior

src/internet/model/arp-header.cc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,14 @@ ArpHeader::Deserialize(Buffer::Iterator start)
212212
}
213213

214214
m_type = static_cast<ArpType_e>(i.ReadNtohU16()); // Read OP
215-
ReadFrom(i, m_macSource, hardwareAddressLen); // Read SHA (size HLN)
216-
ReadFrom(i, m_ipv4Source); // Read SPA (size PLN == 4)
217-
ReadFrom(i, m_macDest, hardwareAddressLen); // Read THA (size HLN)
218-
ReadFrom(i, m_ipv4Dest); // Read TPA (size PLN == 4)
215+
216+
m_macSource.SetType("MacAddress", hardwareAddressLen);
217+
m_macDest.SetType("MacAddress", hardwareAddressLen);
218+
219+
ReadFrom(i, m_macSource, hardwareAddressLen); // Read SHA (size HLN)
220+
ReadFrom(i, m_ipv4Source); // Read SPA (size PLN == 4)
221+
ReadFrom(i, m_macDest, hardwareAddressLen); // Read THA (size HLN)
222+
ReadFrom(i, m_ipv4Dest); // Read TPA (size PLN == 4)
219223
return GetSerializedSize();
220224
}
221225

src/internet/model/icmpv6-header.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2044,6 +2044,7 @@ Icmpv6OptionLinkLayerAddress::Deserialize(Buffer::Iterator start)
20442044
NS_ASSERT(GetLength() * 8 <= 32 + 2);
20452045
i.Read(mac, (GetLength() * 8) - 2);
20462046

2047+
m_addr.SetType("MacAddress", (GetLength() * 8) - 2);
20472048
m_addr.CopyFrom(mac, (GetLength() * 8) - 2);
20482049

20492050
return GetSerializedSize();

src/internet/model/icmpv6-l4-protocol.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,6 @@ Icmpv6L4Protocol::ReceiveLLA(Icmpv6OptionLinkLayerAddress lla,
498498
Ptr<Ipv6Interface> interface)
499499
{
500500
NS_LOG_FUNCTION(this << lla << src << dst << interface);
501-
Address hardwareAddress;
502501
NdiscCache::Entry* entry = nullptr;
503502
Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
504503

@@ -843,7 +842,6 @@ Icmpv6L4Protocol::HandleNA(Ptr<Packet> packet,
843842
packet->RemoveHeader(naHeader);
844843
Ipv6Address target = naHeader.GetIpv6Target();
845844

846-
Address hardwareAddress;
847845
NdiscCache::Entry* entry = nullptr;
848846
Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
849847
std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;

src/internet/test/neighbor-cache-test.cc

Lines changed: 165 additions & 165 deletions
Large diffs are not rendered by default.

src/network/model/address.cc

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ namespace ns3
2020

2121
NS_LOG_COMPONENT_DEFINE("Address");
2222

23+
Address::KindTypeRegistry Address::m_typeRegistry;
24+
2325
Address::Address()
24-
: m_type(0),
26+
: m_type(UNASSIGNED_TYPE),
2527
m_len(0)
2628
{
2729
// Buffer left uninitialized
@@ -33,7 +35,8 @@ Address::Address(uint8_t type, const uint8_t* buffer, uint8_t len)
3335
m_len(len)
3436
{
3537
NS_LOG_FUNCTION(this << static_cast<uint32_t>(type) << &buffer << static_cast<uint32_t>(len));
36-
NS_ASSERT(m_len <= MAX_SIZE);
38+
NS_ASSERT_MSG(m_len <= MAX_SIZE, "Address length too large");
39+
NS_ASSERT_MSG(type != UNASSIGNED_TYPE, "Type 0 is reserved for uninitialized addresses.");
3740
std::memcpy(m_data, buffer, m_len);
3841
}
3942

@@ -56,11 +59,29 @@ Address::operator=(const Address& address)
5659
return *this;
5760
}
5861

62+
void
63+
Address::SetType(const std::string& kind, uint8_t length)
64+
{
65+
NS_LOG_FUNCTION(this << kind << static_cast<uint32_t>(length));
66+
auto search = m_typeRegistry.find({kind, length});
67+
NS_ASSERT_MSG(search != m_typeRegistry.end(),
68+
"No address with the given kind and length is registered.");
69+
70+
if (m_type != search->second)
71+
{
72+
NS_ASSERT_MSG(m_type == UNASSIGNED_TYPE,
73+
"You can only change the type of a type-0 address."
74+
<< static_cast<uint32_t>(m_type));
75+
76+
m_type = search->second;
77+
}
78+
}
79+
5980
bool
6081
Address::IsInvalid() const
6182
{
6283
NS_LOG_FUNCTION(this);
63-
return m_len == 0 && m_type == 0;
84+
return m_len == 0 && m_type == UNASSIGNED_TYPE;
6485
}
6586

6687
uint8_t
@@ -95,7 +116,9 @@ uint32_t
95116
Address::CopyFrom(const uint8_t* buffer, uint8_t len)
96117
{
97118
NS_LOG_FUNCTION(this << &buffer << static_cast<uint32_t>(len));
98-
NS_ASSERT(len <= MAX_SIZE);
119+
NS_ASSERT_MSG(m_len <= MAX_SIZE, "Address length too large");
120+
NS_ASSERT_MSG(m_type != UNASSIGNED_TYPE,
121+
"Type-0 addresses are reserved. Please use SetType before using CopyFrom.");
99122
std::memcpy(m_data, buffer, len);
100123
m_len = len;
101124
return m_len;
@@ -119,9 +142,7 @@ Address::CheckCompatible(uint8_t type, uint8_t len) const
119142
{
120143
NS_LOG_FUNCTION(this << static_cast<uint32_t>(type) << static_cast<uint32_t>(len));
121144
NS_ASSERT(len <= MAX_SIZE);
122-
/// @internal
123-
/// Mac address type/length detection is discussed in \bugid{1568}
124-
return (m_len == len && m_type == type) || (m_len >= len && m_type == 0);
145+
return (m_len == len && m_type == type);
125146
}
126147

127148
bool
@@ -132,12 +153,15 @@ Address::IsMatchingType(uint8_t type) const
132153
}
133154

134155
uint8_t
135-
Address::Register()
156+
Address::Register(const std::string& kind, uint8_t length)
136157
{
137-
NS_LOG_FUNCTION_NOARGS();
138-
static uint8_t type = 1;
139-
type++;
140-
return type;
158+
NS_LOG_FUNCTION(kind << length);
159+
static uint8_t lastRegisteredType = UNASSIGNED_TYPE;
160+
NS_ASSERT_MSG(m_typeRegistry.find({kind, length}) == m_typeRegistry.end(),
161+
"An address of the same kind and length is already registered.");
162+
lastRegisteredType++;
163+
m_typeRegistry[{kind, length}] = lastRegisteredType;
164+
return lastRegisteredType;
141165
}
142166

143167
uint32_t
@@ -171,16 +195,7 @@ ATTRIBUTE_HELPER_CPP(Address);
171195
bool
172196
operator==(const Address& a, const Address& b)
173197
{
174-
/* Two addresses can be equal even if their types are
175-
* different if one of the two types is zero. a type of
176-
* zero identifies an Address which might contain meaningful
177-
* payload but for which the type field could not be set because
178-
* we did not know it. This can typically happen in the ARP
179-
* layer where we receive an address from an ArpHeader but
180-
* we do not know its type: we really want to be able to
181-
* compare addresses without knowing their real type.
182-
*/
183-
if (a.m_type != b.m_type && a.m_type != 0 && b.m_type != 0)
198+
if (a.m_type != b.m_type)
184199
{
185200
return false;
186201
}
@@ -238,8 +253,9 @@ operator<<(std::ostream& os, const Address& address)
238253
{
239254
return os;
240255
}
256+
std::ios_base::fmtflags ff = os.flags();
257+
auto fill = os.fill('0');
241258
os.setf(std::ios::hex, std::ios::basefield);
242-
os.fill('0');
243259
os << std::setw(2) << (uint32_t)address.m_type << "-" << std::setw(2) << (uint32_t)address.m_len
244260
<< "-";
245261
for (uint8_t i = 0; i < (address.m_len - 1); ++i)
@@ -248,8 +264,8 @@ operator<<(std::ostream& os, const Address& address)
248264
}
249265
// Final byte not suffixed by ":"
250266
os << std::setw(2) << (uint32_t)address.m_data[address.m_len - 1];
251-
os.setf(std::ios::dec, std::ios::basefield);
252-
os.fill(' ');
267+
os.flags(ff); // Restore stream flags
268+
os.fill(fill);
253269
return os;
254270
}
255271

0 commit comments

Comments
 (0)