From 90e82767586f250585af886a459496398638932d Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 6 Sep 2017 10:10:15 -0500 Subject: [PATCH] fixup point to point interface handling. with bcast interfaces, send searches to bcast address and !WIN32 binds bcast address to receive searches. with point to point, send searches to dest address. can't bind dest address (not local). quiets spurious error message: > Error binding socket: Cannot assign requested address. Encountered with a P2P link setup by openvpn. --- src/remote/blockingUDPTransport.cpp | 11 ++++++----- src/utils/inetAddressUtil.cpp | 21 ++++++++++++--------- src/utils/pv/inetAddressUtil.h | 13 ++++++++++++- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/remote/blockingUDPTransport.cpp b/src/remote/blockingUDPTransport.cpp index afa4730..c656cdd 100644 --- a/src/remote/blockingUDPTransport.cpp +++ b/src/remote/blockingUDPTransport.cpp @@ -602,10 +602,10 @@ void initializeUDPTransports(bool serverFlag, { ifaceNode node = *iter; - if (node.ifaceBCast.ia.sin_family != AF_UNSPEC) + if (node.ifaceDest.ia.sin_family != AF_UNSPEC) { - node.ifaceBCast.ia.sin_port = htons(sendPort); - autoBCastAddr.push_back(node.ifaceBCast); + node.ifaceDest.ia.sin_port = htons(sendPort); + autoBCastAddr.push_back(node.ifaceDest); } } @@ -681,9 +681,10 @@ void initializeUDPTransports(bool serverFlag, { ifaceNode node = *iter; - LOG(logLevelDebug, "Setting up UDP for interface %s, broadcast %s.", + LOG(logLevelDebug, "Setting up UDP for interface %s, broadcast %s, dest %s.", inetAddressToString(node.ifaceAddr, false).c_str(), - inetAddressToString(node.ifaceBCast, false).c_str()); + inetAddressToString(node.ifaceBCast, false).c_str(), + inetAddressToString(node.ifaceDest, false).c_str()); try { // where to bind (listen) address diff --git a/src/utils/inetAddressUtil.cpp b/src/utils/inetAddressUtil.cpp index 111c9a6..3e148c1 100644 --- a/src/utils/inetAddressUtil.cpp +++ b/src/utils/inetAddressUtil.cpp @@ -211,7 +211,14 @@ int getLoopbackNIF(osiSockAddr &loAddr, string const & localNIF, unsigned short return 1; } - +ifaceNode::ifaceNode() +{ + memset(&ifaceAddr, 0, sizeof(ifaceAddr)); + memset(&ifaceBCast, 0, sizeof(ifaceBCast)); + memset(&ifaceDest, 0, sizeof(ifaceDest)); + // redundant as AF_UNSPEC==0 + ifaceAddr.sa.sa_family = ifaceBCast.sa.sa_family = ifaceDest.sa.sa_family = AF_UNSPEC; +} #include //#include @@ -371,7 +378,7 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr * errlogPrintf ("discoverInterfaces(): net intf \"%s\": bcast addr fetch fail\n", pIfreqList->ifr_name); continue; } - node.ifaceBCast.sa = pIfreqList->ifr_broadaddr; + node.ifaceBCast.sa = node.ifaceDest.sa = pIfreqList->ifr_broadaddr; /*ifDepenDebugPrintf ( ( "found broadcast addr = %x\n", ntohl ( pNewNode->addr.ia.sin_addr.s_addr ) ) );*/ } #if defined (IFF_POINTOPOINT) @@ -381,16 +388,12 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr * /*ifDepenDebugPrintf ( ("discoverInterfaces(): net intf \"%s\": pt to pt addr fetch fail\n", pIfreqList->ifr_name) );*/ continue; } - node.ifaceBCast.sa = pIfreqList->ifr_dstaddr; + node.ifaceDest.sa = pIfreqList->ifr_dstaddr; } #endif else { - // if it is a match, accept the interface even if it does not support broadcast (i.e. 127.0.0.1) - if (match) { - memset(&node.ifaceBCast, 0, sizeof(node.ifaceBCast)); - node.ifaceBCast.sa.sa_family = AF_UNSPEC; - } - else + // if it is a match, accept the interface even if it does not support broadcast (i.e. 127.0.0.1 or point to point) + if (!match) { /*ifDepenDebugPrintf ( ( "discoverInterfaces(): net intf \"%s\": not point to point or bcast?\n", pIfreqList->ifr_name ) );*/ continue; diff --git a/src/utils/pv/inetAddressUtil.h b/src/utils/pv/inetAddressUtil.h index cdf03d4..31e05e5 100644 --- a/src/utils/pv/inetAddressUtil.h +++ b/src/utils/pv/inetAddressUtil.h @@ -31,8 +31,19 @@ typedef std::vector InetAddrVector; */ epicsShareFunc void getBroadcastAddresses(InetAddrVector& ret, SOCKET sock, unsigned short defaultPort); +/** interface description + * ifaceAddr - Local address of interface. Will never be AF_UNSPEC + * ifaceBCast - Broadcast address of interface. + * AF_UNSPEC for loopback and point to point (eg. some VPNs) + * !WIN32 bind this to receive bcasts. + * ifaceDest - Destination/Peer for point to point. + * Copy of ifaceBCast for bcast. + * AF_UNSPEC for loopback. + * send UDP searches to this address + */ struct ifaceNode { - osiSockAddr ifaceAddr, ifaceBCast; + osiSockAddr ifaceAddr, ifaceBCast, ifaceDest; + ifaceNode(); }; typedef std::vector IfaceNodeVector; epicsShareFunc int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *pMatchAddr = 0);