Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit e994509

Browse files
committed
Bug 1583204 - No Network ID is available when switching between WiFi and Lan networks, r=valentin
There can be multiple records for the same neighbor with different interface index when the computer is connected to the same network via multiple interfaces, e.g. LAN and WiFi. This patch adds interface index to the key, so when some interface goes down it doesn't remove records belonging to a different interface. Differential Revision: https://phabricator.services.mozilla.com/D47017 --HG-- extra : moz-landing-system : lando
1 parent 4c49dab commit e994509

2 files changed

Lines changed: 80 additions & 33 deletions

File tree

netwerk/system/netlink/NetlinkService.cpp

Lines changed: 79 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ static void GetAddrStr(const in_common_addr* aAddr, uint8_t aFamily,
5656
_retval.Assign(addr);
5757
}
5858

59+
static void GetNeighborKey(const in_common_addr* aAddr, uint8_t aFamily,
60+
uint32_t aIfIndex, nsACString& _retval) {
61+
GetAddrStr(aAddr, aFamily, _retval);
62+
_retval.Append(",");
63+
_retval.AppendInt(aIfIndex);
64+
}
65+
5966
class NetlinkAddress {
6067
public:
6168
NetlinkAddress() {}
@@ -129,6 +136,7 @@ class NetlinkNeighbor {
129136
NetlinkNeighbor() : mHasMAC(false) {}
130137

131138
uint8_t Family() const { return mNeigh.ndm_family; }
139+
uint32_t GetIndex() const { return mNeigh.ndm_ifindex; }
132140
const in_common_addr* GetAddrPtr() const { return &mAddr; }
133141
const uint8_t* GetMACPtr() const { return mMAC; }
134142
bool HasMAC() const { return mHasMAC; };
@@ -246,7 +254,8 @@ class NetlinkRoute {
246254
: mHasGWAddr(false),
247255
mHasPrefSrcAddr(false),
248256
mHasDstAddr(false),
249-
mHasOif(false) {}
257+
mHasOif(false),
258+
mHasPrio(false) {}
250259

251260
bool IsUnicast() const { return mRtm.rtm_type == RTN_UNICAST; }
252261
bool IsDefault() const { return mRtm.rtm_dst_len == 0; }
@@ -270,6 +279,9 @@ class NetlinkRoute {
270279
if (mHasOif != aOther->mHasOif || mOif != aOther->mOif) {
271280
return false;
272281
}
282+
if (mHasPrio != aOther->mHasPrio || mPrio != aOther->mPrio) {
283+
return false;
284+
}
273285
if ((mHasGWAddr != aOther->mHasGWAddr) ||
274286
(mHasGWAddr && memcmp(&mGWAddr, &(aOther->mGWAddr), addrSize))) {
275287
return false;
@@ -356,6 +368,10 @@ class NetlinkRoute {
356368
_retval.Append(" oif=");
357369
_retval.AppendInt(mOif);
358370
}
371+
if (mHasPrio) {
372+
_retval.Append(" prio=");
373+
_retval.AppendInt(mPrio);
374+
}
359375
}
360376
#endif
361377

@@ -390,6 +406,9 @@ class NetlinkRoute {
390406
} else if (attr->rta_type == RTA_OIF) {
391407
mOif = *(uint32_t*)RTA_DATA(attr);
392408
mHasOif = true;
409+
} else if (attr->rta_type == RTA_PRIORITY) {
410+
mPrio = *(uint32_t*)RTA_DATA(attr);
411+
mHasPrio = true;
393412
}
394413
}
395414

@@ -402,12 +421,14 @@ class NetlinkRoute {
402421
bool mHasPrefSrcAddr : 1;
403422
bool mHasDstAddr : 1;
404423
bool mHasOif : 1;
424+
bool mHasPrio : 1;
405425

406426
in_common_addr mGWAddr;
407427
in_common_addr mDstAddr;
408428
in_common_addr mPrefSrcAddr;
409429

410430
uint32_t mOif;
431+
uint32_t mPrio;
411432
struct rtmsg mRtm;
412433
};
413434

@@ -536,7 +557,7 @@ NetlinkService::NetlinkService()
536557
mInitialScanFinished(false),
537558
mDoRouteCheckIPv4(false),
538559
mDoRouteCheckIPv6(false),
539-
mMsgId(1),
560+
mMsgId(0),
540561
mLinkUp(true),
541562
mRecalculateNetworkId(false) {
542563
mPid = getpid();
@@ -610,11 +631,13 @@ void NetlinkService::OnNetlinkMessage(int aNetlinkSocket) {
610631
switch (nlh->nlmsg_type) {
611632
case NLMSG_DONE: /* Message signalling end of dump for responses to
612633
request containing NLM_F_DUMP flag */
634+
LOG(("received NLMSG_DONE"));
613635
if (isResponse) {
614636
RemovePendingMsg();
615637
}
616638
break;
617639
case NLMSG_ERROR:
640+
LOG(("received NLMSG_ERROR"));
618641
if (isResponse) {
619642
if (mOutgoingMessages[0]->MsgType() == NetlinkMsg::kRtMsg) {
620643
OnRouteCheckResult(nullptr);
@@ -659,7 +682,9 @@ void NetlinkService::OnNetlinkMessage(int aNetlinkSocket) {
659682
}
660683

661684
void NetlinkService::OnLinkMessage(struct nlmsghdr* aNlh) {
662-
LOG(("NetlinkService::OnLinkMessage"));
685+
LOG(("NetlinkService::OnLinkMessage [type=%s]",
686+
aNlh->nlmsg_type == RTM_NEWLINK ? "new" : "del"));
687+
663688
nsAutoPtr<NetlinkLink> link(new NetlinkLink());
664689
if (!link->Init(aNlh)) {
665690
return;
@@ -737,7 +762,9 @@ void NetlinkService::CheckLinks() {
737762
}
738763

739764
void NetlinkService::OnAddrMessage(struct nlmsghdr* aNlh) {
740-
LOG(("NetlinkService::OnAddrMessage"));
765+
LOG(("NetlinkService::OnAddrMessage [type=%s]",
766+
aNlh->nlmsg_type == RTM_NEWADDR ? "new" : "del"));
767+
741768
nsAutoPtr<NetlinkAddress> address(new NetlinkAddress());
742769
if (!address->Init(aNlh)) {
743770
return;
@@ -779,7 +806,9 @@ void NetlinkService::OnAddrMessage(struct nlmsghdr* aNlh) {
779806
}
780807

781808
void NetlinkService::OnRouteMessage(struct nlmsghdr* aNlh) {
782-
LOG(("NetlinkService::OnRouteMessage"));
809+
LOG(("NetlinkService::OnRouteMessage [type=%s]",
810+
aNlh->nlmsg_type == RTM_NEWROUTE ? "new" : "del"));
811+
783812
nsAutoPtr<NetlinkRoute> route(new NetlinkRoute());
784813
if (!route->Init(aNlh)) {
785814
return;
@@ -806,9 +835,9 @@ void NetlinkService::OnRouteMessage(struct nlmsghdr* aNlh) {
806835
if (!route->IsDefault()) {
807836
// Store only default routes
808837
#ifdef NL_DEBUG_LOG
809-
LOG(("Not storing non-unicast route: %s", routeDbgStr.get()));
838+
LOG(("Not a default route: %s", routeDbgStr.get()));
810839
#else
811-
LOG(("Not storing non-unicast route"));
840+
LOG(("Not a default route"));
812841
#endif
813842
return;
814843
}
@@ -845,14 +874,17 @@ void NetlinkService::OnRouteMessage(struct nlmsghdr* aNlh) {
845874
}
846875

847876
void NetlinkService::OnNeighborMessage(struct nlmsghdr* aNlh) {
848-
LOG(("NetlinkService::OnNeighborMessage"));
877+
LOG(("NetlinkService::OnNeighborMessage [type=%s]",
878+
aNlh->nlmsg_type == RTM_NEWNEIGH ? "new" : "del"));
879+
849880
nsAutoPtr<NetlinkNeighbor> neigh(new NetlinkNeighbor());
850881
if (!neigh->Init(aNlh)) {
851882
return;
852883
}
853884

854-
nsAutoCString addrStr;
855-
GetAddrStr(neigh->GetAddrPtr(), neigh->Family(), addrStr);
885+
nsAutoCString neighKey;
886+
GetNeighborKey(neigh->GetAddrPtr(), neigh->Family(), neigh->GetIndex(),
887+
neighKey);
856888

857889
nsTArray<nsAutoPtr<NetlinkRoute> >* routesPtr;
858890
nsAutoPtr<NetlinkRoute>* routeCheckResultPtr;
@@ -867,7 +899,7 @@ void NetlinkService::OnNeighborMessage(struct nlmsghdr* aNlh) {
867899
if (aNlh->nlmsg_type == RTM_NEWNEIGH) {
868900
if (!mRecalculateNetworkId && neigh->HasMAC()) {
869901
NetlinkNeighbor* oldNeigh = nullptr;
870-
mNeighbors.Get(addrStr, &oldNeigh);
902+
mNeighbors.Get(neighKey, &oldNeigh);
871903

872904
if (!oldNeigh || !oldNeigh->HasMAC()) {
873905
// The MAC address was added, if it's a host from some of the saved
@@ -890,14 +922,14 @@ void NetlinkService::OnNeighborMessage(struct nlmsghdr* aNlh) {
890922
neigh->GetAsString(neighDbgStr);
891923
LOG(("Adding neighbor: %s", neighDbgStr.get()));
892924
#else
893-
LOG(("Adding neighbor %s", addrStr.get()));
925+
LOG(("Adding neighbor %s", neighKey.get()));
894926
#endif
895-
mNeighbors.Put(addrStr, neigh.forget());
927+
mNeighbors.Put(neighKey, neigh.forget());
896928
} else {
897929
#ifdef NL_DEBUG_LOG
898-
LOG(("Removing neighbor %s", addrStr.get()));
930+
LOG(("Removing neighbor %s", neighKey.get()));
899931
#endif
900-
mNeighbors.Remove(addrStr);
932+
mNeighbors.Remove(neighKey);
901933
}
902934
}
903935

@@ -937,7 +969,7 @@ void NetlinkService::OnRouteCheckResult(struct nlmsghdr* aNlh) {
937969
LOG(("Storing result for the check"));
938970
#endif
939971
} else {
940-
LOG(("Clearing result for the checkd"));
972+
LOG(("Clearing result for the check"));
941973
}
942974

943975
(*routeCheckResultPtr) = route.forget();
@@ -954,6 +986,9 @@ void NetlinkService::EnqueueRtMsg(uint8_t aFamily, void* aAddress) {
954986
}
955987

956988
void NetlinkService::RemovePendingMsg() {
989+
LOG(("NetlinkService::RemovePendingMsg [seqId=%u]",
990+
mOutgoingMessages[0]->SeqId()));
991+
957992
MOZ_ASSERT(mOutgoingMessages[0]->IsPending());
958993

959994
DebugOnly<bool> isRtMessage =
@@ -1219,33 +1254,42 @@ bool NetlinkService::CalculateIDForFamily(uint8_t aFamily, SHA1Sum* aSHA1) {
12191254
(*routesPtr)[i]->GetAsString(routeDbgStr);
12201255
LOG(("Checking default route: %s", routeDbgStr.get()));
12211256
#endif
1222-
nsAutoCString addrStr;
1257+
if (!(*routesPtr)[i]->HasOif()) {
1258+
LOG(("There is no output interface in default route."));
1259+
continue;
1260+
}
1261+
1262+
nsAutoCString neighKey;
12231263
const in_common_addr* addrPtr = (*routesPtr)[i]->GetGWAddrPtr();
12241264
if (!addrPtr) {
12251265
LOG(("There is no GW address in default route."));
12261266
continue;
12271267
}
12281268

1229-
GetAddrStr(addrPtr, (*routesPtr)[i]->Family(), addrStr);
1269+
GetNeighborKey(addrPtr, (*routesPtr)[i]->Family(), (*routesPtr)[i]->Oif(),
1270+
neighKey);
1271+
12301272
NetlinkNeighbor* neigh = nullptr;
1231-
if (!mNeighbors.Get(addrStr, &neigh)) {
1232-
LOG(("Neighbor %s not found in hashtable.", addrStr.get()));
1273+
if (!mNeighbors.Get(neighKey, &neigh)) {
1274+
LOG(("Neighbor %s not found in hashtable.", neighKey.get()));
12331275
continue;
12341276
}
12351277

12361278
if (!neigh->HasMAC()) {
12371279
// We don't know MAC address
1238-
LOG(("We have no MAC for neighbor %s.", addrStr.get()));
1280+
LOG(("We have no MAC for neighbor %s.", neighKey.get()));
12391281
continue;
12401282
}
12411283

1242-
if (gwNeighbors.IndexOf(neigh) != gwNeighbors.NoIndex) {
1284+
if (gwNeighbors.IndexOf(neigh, 0, NeighborComparator()) !=
1285+
nsTArray<NetlinkNeighbor*>::NoIndex) {
12431286
// avoid host duplicities
1244-
LOG(("Neighbor %s is already selected for hashing.", addrStr.get()));
1287+
LOG(("MAC of neighbor %s is already selected for hashing.",
1288+
neighKey.get()));
12451289
continue;
12461290
}
12471291

1248-
LOG(("Neighbor %s will be used for network ID.", addrStr.get()));
1292+
LOG(("MAC of neighbor %s will be used for network ID.", neighKey.get()));
12491293
gwNeighbors.AppendElement(neigh);
12501294
}
12511295

@@ -1311,24 +1355,25 @@ bool NetlinkService::CalculateIDForFamily(uint8_t aFamily, SHA1Sum* aSHA1) {
13111355

13121356
// Check whether we know next hop for mRouteCheckIPv4/6 host
13131357
const in_common_addr* addrPtr = (*routeCheckResultPtr)->GetGWAddrPtr();
1314-
if (addrPtr) {
1358+
if (addrPtr && (*routeCheckResultPtr)->HasOif()) {
13151359
// If we know MAC address of the next hop for mRouteCheckIPv4/6 host, hash
13161360
// it even if it's MAC of some of the default routes we've checked above.
13171361
// This ensures that if we have 2 different default routes and next hop for
13181362
// mRouteCheckIPv4/6 changes from one default route to the other, we'll
13191363
// detect it as a network change.
1320-
nsAutoCString addrStr;
1321-
GetAddrStr(addrPtr, (*routeCheckResultPtr)->Family(), addrStr);
1322-
LOG(("Next hop for the checked host is %s.", addrStr.get()));
1364+
nsAutoCString neighKey;
1365+
GetNeighborKey(addrPtr, (*routeCheckResultPtr)->Family(),
1366+
(*routeCheckResultPtr)->Oif(), neighKey);
1367+
LOG(("Next hop for the checked host is %s.", neighKey.get()));
13231368

13241369
NetlinkNeighbor* neigh = nullptr;
1325-
if (!mNeighbors.Get(addrStr, &neigh)) {
1326-
LOG(("Neighbor %s not found in hashtable.", addrStr.get()));
1370+
if (!mNeighbors.Get(neighKey, &neigh)) {
1371+
LOG(("Neighbor %s not found in hashtable.", neighKey.get()));
13271372
return retval;
13281373
}
13291374

13301375
if (!neigh->HasMAC()) {
1331-
LOG(("We have no MAC for neighbor %s.", addrStr.get()));
1376+
LOG(("We have no MAC for neighbor %s.", neighKey.get()));
13321377
return retval;
13331378
}
13341379

@@ -1337,7 +1382,7 @@ bool NetlinkService::CalculateIDForFamily(uint8_t aFamily, SHA1Sum* aSHA1) {
13371382
neigh->GetAsString(neighDbgStr);
13381383
LOG(("Hashing MAC address of neighbor: %s", neighDbgStr.get()));
13391384
#else
1340-
LOG(("Hashing MAC address of neighbor %s", addrStr.get()));
1385+
LOG(("Hashing MAC address of neighbor %s", neighKey.get()));
13411386
#endif
13421387
aSHA1->update(neigh->GetMACPtr(), ETH_ALEN);
13431388
retval = true;
@@ -1445,6 +1490,8 @@ bool NetlinkService::CalculateIDForFamily(uint8_t aFamily, SHA1Sum* aSHA1) {
14451490

14461491
// Figure out the "network identification".
14471492
void NetlinkService::CalculateNetworkID() {
1493+
LOG(("NetlinkService::CalculateNetworkID"));
1494+
14481495
MOZ_ASSERT(!NS_IsMainThread(), "Must not be called on the main thread");
14491496
MOZ_ASSERT(mRecalculateNetworkId);
14501497

netwerk/system/netlink/NetlinkService.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class NetlinkService : public nsIRunnable {
111111

112112
// All IPv4 and IPv6 addresses received via netlink
113113
nsTArray<nsAutoPtr<NetlinkAddress> > mAddresses;
114-
// All neighbors, key is an address
114+
// All neighbors, key is a string containing "address,ifidx"
115115
nsClassHashtable<nsCStringHashKey, NetlinkNeighbor> mNeighbors;
116116
// All interfaces keyed by interface index
117117
nsClassHashtable<nsUint32HashKey, NetlinkLink> mLinks;

0 commit comments

Comments
 (0)