diff --git a/src/ca/legacy/pcas/generic/caServerI.cc b/src/ca/legacy/pcas/generic/caServerI.cc index af7ece1eb..13e01ed55 100644 --- a/src/ca/legacy/pcas/generic/caServerI.cc +++ b/src/ca/legacy/pcas/generic/caServerI.cc @@ -141,6 +141,38 @@ caStatus caServerI::attachInterface ( const caNetAddr & addrIn, return S_cas_success; } +void caServerI::addMCast(const osiSockAddr& addr) +{ +#ifdef IP_ADD_MEMBERSHIP + epicsGuard < epicsMutex > locker ( this->mutex ); + tsDLIter < casIntfOS > iter = this->intfList.firstIter (); + while ( iter.valid () ) { + struct ip_mreq mreq; + + memset(&mreq, 0, sizeof(mreq)); + mreq.imr_interface = iter->serverAddress().getSockIP().sin_addr; + mreq.imr_multiaddr = addr.ia.sin_addr; + + if(setsockopt(iter->casDGIntfIO::getFD(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))!=0) + { + struct sockaddr_in temp; + char name[40]; + char sockErrBuf[64]; + temp.sin_family = AF_INET; + temp.sin_addr = mreq.imr_multiaddr; + temp.sin_port = addr.ia.sin_port; + epicsSocketConvertErrnoToString ( + sockErrBuf, sizeof ( sockErrBuf ) ); + ipAddrToDottedIP (&temp, name, sizeof(name)); + fprintf(stderr, "CAS: Socket mcast join %s failed with \"%s\"\n", + name, sockErrBuf ); + } + + iter++; + } +#endif +} + void caServerI::sendBeacon ( ca_uint32_t beaconNo ) { epicsGuard < epicsMutex > locker ( this->mutex ); diff --git a/src/ca/legacy/pcas/generic/caServerI.h b/src/ca/legacy/pcas/generic/caServerI.h index 6037d8c20..344f6393b 100644 --- a/src/ca/legacy/pcas/generic/caServerI.h +++ b/src/ca/legacy/pcas/generic/caServerI.h @@ -103,6 +103,8 @@ private: caStatus attachInterface ( const caNetAddr & addr, bool autoBeaconAddr, bool addConfigAddr ); + virtual void addMCast(const osiSockAddr&); + void sendBeacon ( ca_uint32_t beaconNo ); caServerI ( const caServerI & ); diff --git a/src/ca/legacy/pcas/io/bsdSocket/caServerIO.cc b/src/ca/legacy/pcas/io/bsdSocket/caServerIO.cc index 5c5da03ff..8e5c356a6 100644 --- a/src/ca/legacy/pcas/io/bsdSocket/caServerIO.cc +++ b/src/ca/legacy/pcas/io/bsdSocket/caServerIO.cc @@ -14,6 +14,7 @@ // #include +#include #include "epicsSignal.h" #include "envDefs.h" @@ -92,6 +93,9 @@ void caServerIO::locateInterfaces () autoBeaconAddr = true; } + typedef std::list mcastAddrs_t; + mcastAddrs_t mcastAddrs; + // // bind to the the interfaces specified - otherwise wildcard // with INADDR_ANY and allow clients to attach from any interface @@ -114,6 +118,15 @@ void caServerIO::locateInterfaces () pToken); continue; } + + epicsUInt32 top = ntohl(saddr.sin_addr.s_addr)>>24; + if (saddr.sin_family==AF_INET && top>=224 && top<=239) { + osiSockAddr oaddr; + oaddr.ia = saddr; + mcastAddrs.push_back(oaddr); + continue; + } + stat = this->attachInterface (caNetAddr(saddr), autoBeaconAddr, configAddrOnceFlag); if (stat) { errMessage(stat, "unable to attach explicit interface"); @@ -131,6 +144,10 @@ void caServerIO::locateInterfaces () errMessage(stat, "unable to attach any interface"); } } + + for (mcastAddrs_t::const_iterator it = mcastAddrs.begin(); it!=mcastAddrs.end(); ++it) { + this->addMCast(*it); + } } // diff --git a/src/ca/legacy/pcas/io/bsdSocket/caServerIO.h b/src/ca/legacy/pcas/io/bsdSocket/caServerIO.h index b24afb5f8..b45903cff 100644 --- a/src/ca/legacy/pcas/io/bsdSocket/caServerIO.h +++ b/src/ca/legacy/pcas/io/bsdSocket/caServerIO.h @@ -47,6 +47,8 @@ private: virtual caStatus attachInterface ( const caNetAddr & addr, bool autoBeaconAddr, bool addConfigAddr ) = 0; + + virtual void addMCast(const osiSockAddr&) = 0; }; #endif // caServerIOh