libCom/osi: osiSockDiscoverBroadcastAddresses() finds 127.255.255.255

For the default implementation of osiSockDiscoverBroadcastAddresses()
allow the loopback interface to have IFF_BROADCAST set (usually isn't)
and on Linux assume that the loopback broadcast address is usable
even if IFF_BROADCAST isn't set.
This commit is contained in:
Michael Davidsaver
2016-01-11 20:59:07 -05:00
parent c80f71e294
commit e805abe971

View File

@@ -73,21 +73,6 @@ epicsShareFunc void epicsShareAPI osiSockDiscoverBroadcastAddresses
struct ifreq *pifreq;
struct ifreq *pnextifreq;
osiSockAddrNode *pNewNode;
if ( pMatchAddr->sa.sa_family == AF_INET ) {
if ( pMatchAddr->ia.sin_addr.s_addr == htonl (INADDR_LOOPBACK) ) {
pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) );
if ( pNewNode == NULL ) {
errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
return;
}
pNewNode->addr.ia.sin_family = AF_INET;
pNewNode->addr.ia.sin_port = htons ( 0 );
pNewNode->addr.ia.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
ellAdd ( pList, &pNewNode->node );
return;
}
}
/*
* use pool so that we avoid using too much stack space
@@ -116,6 +101,7 @@ epicsShareFunc void epicsShareAPI osiSockDiscoverBroadcastAddresses
for ( pifreq = pIfreqList; pifreq <= pIfreqListEnd; pifreq = pnextifreq ) {
uint32_t current_ifreqsize;
struct sockaddr_in if_addr;
/*
* find the next ifreq
@@ -139,6 +125,7 @@ epicsShareFunc void epicsShareAPI osiSockDiscoverBroadcastAddresses
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): interface \"%s\" was not AF_INET\n", pIfreqList->ifr_name) );
continue;
}
if_addr = *(struct sockaddr_in *)&pIfreqList->ifr_addr;
/*
* if it isnt a wildcarded interface then look for
@@ -149,8 +136,7 @@ epicsShareFunc void epicsShareAPI osiSockDiscoverBroadcastAddresses
continue;
}
if ( pMatchAddr->ia.sin_addr.s_addr != htonl (INADDR_ANY) ) {
struct sockaddr_in *pInetAddr = (struct sockaddr_in *) &pIfreqList->ifr_addr;
if ( pInetAddr->sin_addr.s_addr != pMatchAddr->ia.sin_addr.s_addr ) {
if ( if_addr.sin_addr.s_addr != pMatchAddr->ia.sin_addr.s_addr ) {
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" didnt match\n", pIfreqList->ifr_name) );
continue;
}
@@ -171,14 +157,6 @@ epicsShareFunc void epicsShareAPI osiSockDiscoverBroadcastAddresses
continue;
}
/*
* dont use the loop back interface
*/
if ( pIfreqList->ifr_flags & IFF_LOOPBACK ) {
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): ignoring loopback interface: \"%s\"\n", pIfreqList->ifr_name) );
continue;
}
pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) );
if ( pNewNode == NULL ) {
errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
@@ -216,6 +194,22 @@ epicsShareFunc void epicsShareAPI osiSockDiscoverBroadcastAddresses
}
pNewNode->addr.sa = pIfreqList->ifr_dstaddr;
}
#endif
#if defined(__linux__)
/* On Linux, even though the 'lo' interface doesn't set IFF_BROADCAST
* a broadcast route often exists. Assume that sending to 127.255.255.255
* reaches all local listeners.
*
* $ ip route show table local scope link dev lo
* broadcast 127.0.0.0 proto kernel src 127.0.0.1
* broadcast 127.255.255.255 proto kernel src 127.0.0.1
*/
else if ( pIfreqList->ifr_flags & IFF_LOOPBACK && if_addr.sin_addr.s_addr == htonl(INADDR_LOOPBACK) ) {
memset(&pNewNode->addr.ia, 0, sizeof(pNewNode->addr.ia));
pNewNode->addr.ia.sin_family = AF_INET;
pNewNode->addr.ia.sin_addr.s_addr = htonl(0x7fffffff);
ifDepenDebugPrintf ( ( "assume loopback broadcast addr = %x\n", ntohl ( pNewNode->addr.ia.sin_addr.s_addr ) ) );
}
#endif
else {
ifDepenDebugPrintf ( ( "osiSockDiscoverBroadcastAddresses(): net intf \"%s\": not point to point or bcast?\n", pIfreqList->ifr_name ) );