rsrv: multicast name lookup

This commit is contained in:
Michael Davidsaver
2016-01-11 20:59:08 -05:00
parent f876bdb42c
commit 568ece9c27
2 changed files with 72 additions and 12 deletions

View File

@@ -268,7 +268,7 @@ SOCKET* rsrv_grap_tcp(unsigned short *port)
}
if(ellCount(&casIntfAddrList)==0)
cantProceed("RSRV has empty interface list");
cantProceed("RSRV has empty interface list\n");
return socks;
}
@@ -290,6 +290,7 @@ void rsrv_build_addr_lists(void)
ellInit ( &casIntfAddrList );
ellInit ( &beaconAddrList );
ellInit ( &casMCastAddrList );
{
ELLLIST temp = ELLLIST_INIT;
@@ -301,16 +302,7 @@ void rsrv_build_addr_lists(void)
removeDuplicateAddresses(&casIntfAddrList, &temp, 0);
}
if (ellCount(&casIntfAddrList) == 0) {
/* default to wildcard 0.0.0.0 */
osiSockAddrNode *pNode = (osiSockAddrNode *) callocMustSucceed( 1, sizeof(*pNode), "rsrv_init" );
pNode->addr.ia.sin_family = AF_INET;
pNode->addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
pNode->addr.ia.sin_port = 0;
ellAdd ( &casIntfAddrList, &pNode->node );
expandbcast = 1;
} else {
{
/* check user provided list */
osiSockAddrNode *pNode, *pNext;
for(pNode = (osiSockAddrNode*)ellFirst(&casIntfAddrList),
@@ -319,6 +311,8 @@ void rsrv_build_addr_lists(void)
pNode = pNext,
pNext = pNext ? (osiSockAddrNode*)ellNext(&pNext->node) : NULL)
{
epicsUInt32 top = ntohl(pNode->addr.ia.sin_addr.s_addr)>>24;
if(pNode->addr.ia.sin_family==AF_INET && pNode->addr.ia.sin_addr.s_addr==htonl(INADDR_ANY))
{
if (ellCount(&casIntfAddrList) != 1) {
@@ -328,10 +322,25 @@ void rsrv_build_addr_lists(void)
} else {
expandbcast = 1;
}
} else if(pNode->addr.ia.sin_family==AF_INET && top>=224 && top<=239) {
/* This is a multi-cast address */
ellDelete(&casIntfAddrList, &pNode->node);
ellAdd(&casMCastAddrList, &pNode->node);
}
}
}
if (ellCount(&casIntfAddrList) == 0) {
/* default to wildcard 0.0.0.0 */
osiSockAddrNode *pNode = (osiSockAddrNode *) callocMustSucceed( 1, sizeof(*pNode), "rsrv_init" );
pNode->addr.ia.sin_family = AF_INET;
pNode->addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
pNode->addr.ia.sin_port = 0;
ellAdd ( &casIntfAddrList, &pNode->node );
expandbcast = 1;
}
addAddrToChannelAccessAddressList ( &beaconAddrList,
&EPICS_CAS_BEACON_ADDR_LIST, ca_beacon_port, 0 );
@@ -518,6 +527,7 @@ int rsrv_init (void)
/* start servers (TCP and UDP(s) for each interface.
*/
{
int havesometcp = 0;
ELLNODE *cur;
int i;
@@ -551,6 +561,43 @@ int rsrv_init (void)
if(tryBind(conf->udp, &conf->udpAddr, "UDP unicast socket"))
goto cleanup;
#ifdef IP_ADD_MEMBERSHIP
/* join UDP socket to any multicast groups */
{
osiSockAddrNode *pNode;
for(pNode = (osiSockAddrNode*)ellFirst(&casMCastAddrList);
pNode;
pNode = (osiSockAddrNode*)ellNext(&pNode->node))
{
struct ip_mreq mreq;
memset(&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr = pNode->addr.ia.sin_addr;
mreq.imr_interface.s_addr = conf->udpAddr.ia.sin_addr.s_addr;
if(setsockopt(conf->udp, 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 = conf->udpAddr.ia.sin_port;
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
ipAddrToDottedIP (&temp, name, sizeof(name));
fprintf(stderr, "CAS: Socket mcast join %s to %s failed with \"%s\"\n",
ifaceName, name, sockErrBuf );
}
}
}
#else
if(ellCount(&casMCastAddrList)){
fprintf(stderr, "IPv4 Multicast name lookup not supported by this target\n");
}
#endif
#if !defined(_WIN32)
/* An oddness of BSD sockets (not winsock) is that binding to
* INADDR_ANY will receive unicast and broadcast, but binding to
@@ -623,6 +670,7 @@ int rsrv_init (void)
}
#endif /* !defined(_WIN32) */
havesometcp = 1;
continue;
cleanup:
epicsSocketDestroy(conf->tcp);
@@ -630,6 +678,9 @@ int rsrv_init (void)
if(conf->udpbcast!=INVALID_SOCKET) epicsSocketDestroy(conf->udpbcast);
free(conf);
}
if(!havesometcp)
cantProceed("CAS: No TCP server started\n");
}
/* servers list is considered read-only from this point */
@@ -830,6 +881,15 @@ void casr (unsigned level)
UNLOCK_CLIENTQ
if (level>=2) {
osiSockAddrNode * pAddr;
for(pAddr = (osiSockAddrNode*)ellFirst(&casMCastAddrList);
pAddr;
pAddr = (osiSockAddrNode*)ellNext(&pAddr->node))
{
char buf[40];
ipAddrToDottedIP (&pAddr->addr.ia, buf, sizeof(buf));
printf("MCast destination %s\n", buf);
}
for(pAddr = (osiSockAddrNode*)ellFirst(&beaconAddrList);
pAddr;
pAddr = (osiSockAddrNode*)ellNext(&pAddr->node))

View File

@@ -176,7 +176,7 @@ GLBLTYPE ELLLIST clientQudp; /* locked by clientQlock */
GLBLTYPE ELLLIST servers; /* rsrv_iface_config::node, read-only after rsrv_init() */
GLBLTYPE ELLLIST beaconAddrList;
GLBLTYPE SOCKET beaconSocket;
GLBLTYPE ELLLIST casIntfAddrList;
GLBLTYPE ELLLIST casIntfAddrList, casMCastAddrList;
GLBLTYPE epicsMutexId clientQlock;
GLBLTYPE BUCKET *pCaBucket; /* locked by clientQlock */
GLBLTYPE void *rsrvClientFreeList;