From e805abe971bb864f3f95c341babb6ec4fff1b464 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 11 Jan 2016 20:59:07 -0500 Subject: [PATCH] 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. --- src/libCom/osi/os/default/osdNetIntf.c | 44 +++++++++++--------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/src/libCom/osi/os/default/osdNetIntf.c b/src/libCom/osi/os/default/osdNetIntf.c index ab36fdf10..61f29ae77 100644 --- a/src/libCom/osi/os/default/osdNetIntf.c +++ b/src/libCom/osi/os/default/osdNetIntf.c @@ -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 ) );