summaryrefslogtreecommitdiffstats
path: root/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.cpp')
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.cpp384
1 files changed, 384 insertions, 0 deletions
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.cpp
new file mode 100644
index 00000000..da3ce4ad
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.cpp
@@ -0,0 +1,384 @@
+//
+// bjsocket.cpp
+// TestTB
+//
+// Created by Terrin Eager on 10/24/12.
+//
+//
+#define __APPLE_USE_RFC_2292
+
+#include <unistd.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+
+#include "bjsocket.h"
+#include "bjstring.h"
+
+
+////////////////////////////
+/// BJSocket
+///////////////////////////
+const BJ_UINT16 BonjourPort = 5353;
+
+BJSocket::BJSocket()
+{
+ socketHandle = 0;
+ buffer = NULL;
+ IPVersion = 0;
+ interfaceID = 0;
+}
+
+BJSocket::~BJSocket()
+{
+
+}
+
+bool BJSocket::Init()
+{
+
+ socketHandle = 0;
+ buffer = (BJ_UINT8*)malloc(MAX_FRAME_SIZE);
+
+ if (buffer == NULL)
+ return false;
+
+ //Setup msghdr;
+ memset(&socketMsghdr, '\0', sizeof(socketMsghdr));
+ socketMsghdr.msg_name = &peerAddr;
+ socketMsghdr.msg_namelen = sizeof(peerAddr);
+ socketMsghdr.msg_iov = socketIovec;
+ socketMsghdr.msg_iovlen = 1;
+ socketIovec[0].iov_base = (char *) buffer;
+ socketIovec[0].iov_len = MAX_FRAME_SIZE;
+
+
+ socketMsghdr.msg_control = socketCmsghdr;
+ socketMsghdr.msg_controllen = sizeof(socketCmsghdr);
+
+ return true;
+
+}
+
+bool BJSocket::CreateListenerIPv4(BJString interfaceName)
+{
+ bool bResult = true;
+ const int onoptval = 1;
+
+ if (socketHandle)
+ Close();
+
+ Init();
+
+
+ if (interfaceName.GetLength() > 0)
+ interfaceID = if_nametoindex(interfaceName.GetBuffer());
+
+
+ socketHandle = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
+// socketHandle = socket(PF_INET,SOCK_DGRAM,IPPROTO_RAW);
+
+ if (-1 == setsockopt(socketHandle,SOL_SOCKET,SO_REUSEPORT,&onoptval,sizeof(onoptval)))
+ {
+ printf("setsockopt for SO_REUSEPORT failed");
+ Close();
+ return false;
+ }
+
+ JoinMulticastv4(interfaceName);
+
+ // set PktInfo to get dest address
+
+ if (-1 == setsockopt(socketHandle, IPPROTO_IP, IP_PKTINFO, &onoptval, sizeof(onoptval)))
+ {
+ printf("setsockopt for IP_PKTINFO failed");
+ Close();
+ return false;
+ }
+
+ // bind to socket
+
+ struct sockaddr_in sa;
+ memset(&sa,0,sizeof(sockaddr_in));
+ sa.sin_len = sizeof(sockaddr_in);
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = INADDR_ANY;
+ sa.sin_port = htons(BonjourPort);
+
+ if (-1 == bind(socketHandle,(struct sockaddr*)&sa,sizeof(sa)))
+ {
+ printf("error in bind: %s\n",strerror(errno));
+ Close();
+ return false;
+ }
+ IPVersion = 4;
+
+ return bResult;
+}
+
+bool BJSocket::CreateListenerIPv6(BJString interfaceName)
+{
+ bool bResult = true;
+ const int onoptval=1;
+
+ if (socketHandle)
+ Close();
+
+ Init();
+
+ if (interfaceName.GetLength() > 0)
+ interfaceID = if_nametoindex(interfaceName.GetBuffer());
+
+ socketHandle = socket(PF_INET6,SOCK_DGRAM,IPPROTO_UDP);
+
+ if (-1 == setsockopt(socketHandle,SOL_SOCKET,SO_REUSEPORT,&onoptval,sizeof(onoptval)))
+ {
+ printf("setsockopt for SO_REUSEPORT failed");
+ Close();
+ return false;
+ }
+
+ JoinMulticastv6(interfaceName);
+
+ // set PktInfo to get dest address
+ if (-1 == setsockopt(socketHandle, IPPROTO_IPV6, IPV6_PKTINFO, &onoptval, sizeof(onoptval)))
+ {
+ printf("setsockopt for IP_PKTINFO failed");
+ Close();
+ return false;
+ }
+
+ // bind to socket
+ struct sockaddr_in6 sa6;
+ memset(&sa6,0,sizeof(sockaddr_in6));
+ sa6.sin6_len = sizeof(sockaddr_in6);
+ sa6.sin6_family = AF_INET6;
+ sa6.sin6_addr = in6addr_any;
+ sa6.sin6_port = htons(BonjourPort);
+
+ if (-1 == bind(socketHandle,(struct sockaddr*)&sa6,sizeof(sa6)))
+ {
+ printf("error in bind: %s\n",strerror(errno));
+ Close();
+ return false;
+ }
+ IPVersion = 6;
+
+ return bResult;
+}
+
+bool BJSocket::Close()
+{
+ bool bResult = true;
+
+ if (socketHandle)
+ close(socketHandle);
+
+ socketHandle = 0;
+
+ return bResult;
+}
+
+int BJSocket::Read()
+{
+ int nLength = (int) recvmsg(socketHandle, &socketMsghdr,0);
+ if (!CheckInterface())
+ return 0;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ m_CurrentFrame.Set(buffer-14-40-8,nLength,tv.tv_sec*1000000ll + tv.tv_usec);
+ return nLength;
+}
+
+BJIPAddr* BJSocket::GetSrcAddr()
+{
+ sourceAddr.Set(&peerAddr);
+ return &sourceAddr;
+}
+
+BJIPAddr* BJSocket::GetDestAddr()
+{
+
+ struct cmsghdr *cmsg;
+
+ for(cmsg = CMSG_FIRSTHDR(&socketMsghdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&socketMsghdr, cmsg))
+ {
+
+ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO)
+ {
+ struct in_pktinfo* pPktInfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+
+ destAddr.Set(&pPktInfo->ipi_addr);
+ }
+ if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO)
+ {
+ struct in6_pktinfo* pPktInfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
+ destAddr.Set(&pPktInfo->ipi6_addr);
+ }
+ }
+ return &destAddr;
+}
+
+bool BJSocket::CheckInterface()
+{
+ if (interfaceID ==0)
+ return true;
+ struct cmsghdr *cmsg;
+
+ bool bFound = false;
+
+ for(cmsg = CMSG_FIRSTHDR(&socketMsghdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&socketMsghdr, cmsg))
+ {
+
+ if ((cmsg->cmsg_level == IPPROTO_IP) && cmsg->cmsg_type == IP_PKTINFO)
+ {
+ bFound = true;
+ struct in_pktinfo* pPktInfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+ if (pPktInfo->ipi_ifindex == interfaceID)
+ return true;
+ else
+ {
+ if (pPktInfo->ipi_ifindex != 4)
+ {
+ sourceAddr.Set(&peerAddr);
+ printf("address:%d %s \n",pPktInfo->ipi_ifindex,sourceAddr.GetString());
+ }
+ }
+ }
+ if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO)
+ {
+ bFound = true;
+ struct in6_pktinfo* pPktInfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
+ if (pPktInfo->ipi6_ifindex == interfaceID)
+ return true;
+ }
+ }
+ if (!bFound)
+ printf("PKTINFO not found \n");
+ return false;
+}
+
+bool BJSocket::IsMulticastPacket()
+{
+ return GetDestAddr()->IsBonjourMulticast();
+
+}
+
+int BJSocket::GetSockectHandle()
+{
+ return socketHandle;
+}
+
+BJ_UINT8* BJSocket::GetBuffer()
+{
+ return buffer;
+}
+
+void BJSocket::JoinMulticastv4(BJString interfaceName)
+{
+ if (interfaceName.GetLength() == 0)
+ {
+ // join Multicast group
+ struct ip_mreq imr;
+ imr.imr_multiaddr.s_addr = inet_addr( "224.0.0.251");
+ imr.imr_interface.s_addr = INADDR_ANY;
+ if (-1 == setsockopt(socketHandle, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)))
+ {
+ printf("setsockopt for IP_ADD_MEMBERSHIP failed");
+ }
+ return;
+ }
+
+ struct ifaddrs *ifa, *orig;
+
+ getifaddrs(&ifa);
+
+ orig = ifa;
+
+ for ( ; ifa; ifa = ifa->ifa_next)
+ {
+ if (interfaceName == ifa->ifa_name && ifa->ifa_addr->sa_family == AF_INET)
+ {
+ struct sockaddr_in *ifa_addr = (struct sockaddr_in *)ifa->ifa_addr;
+ struct ip_mreq imr;
+ imr.imr_multiaddr.s_addr = inet_addr( "224.0.0.251");
+ imr.imr_interface.s_addr = ifa_addr->sin_addr.s_addr;
+ if (-1 == setsockopt(socketHandle, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)))
+ {
+ printf("setsockopt for IP_ADD_MEMBERSHIP failed");
+ }
+ }
+ }
+
+ freeifaddrs(orig);
+
+}
+
+void BJSocket::JoinMulticastv6(BJString interfaceName)
+{
+
+ if (interfaceName.GetLength() == 0)
+ return;
+
+ // join Multicast group
+ struct in6_addr BonjourMultiaddr = {{{ 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB }}};
+ struct ipv6_mreq i6mr;
+ memset(&i6mr,0,sizeof(i6mr));
+ memcpy(&i6mr.ipv6mr_multiaddr, &BonjourMultiaddr, sizeof(BonjourMultiaddr));
+ if (interfaceName.GetLength() > 0)
+ i6mr.ipv6mr_interface = interfaceID;
+ else
+ i6mr.ipv6mr_interface = __IPV6_ADDR_SCOPE_SITELOCAL;
+ int err = setsockopt(socketHandle, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr));
+ if (err < 0 && (errno != EADDRINUSE))
+ {
+ printf("setsockopt for IPV6_JOIN_GROUP failed %d",errno);
+ }
+}
+
+////////////////////////////////////////
+// BJSelect
+///////////////////////////////////////
+
+
+BJSelect::BJSelect()
+{
+ FD_ZERO(&socketSet);
+ maxSocket = 0;
+
+}
+
+bool BJSelect::Add(BJSocket& s)
+{
+ int sock = s.GetSockectHandle();
+ FD_SET(sock, &socketSet);
+ if (sock > maxSocket)
+ maxSocket = sock;
+
+ return true;
+
+}
+
+int BJSelect::Wait(int sec)
+{
+ struct timeval tv;
+ memset(&tv, 0, sizeof(tv));
+ tv.tv_sec = sec;
+
+ int result = select(maxSocket+1, &socketSet, NULL, NULL, &tv);
+ return result;
+
+}
+
+bool BJSelect::IsReady(BJSocket& Socket)
+{
+ int bIsSet = FD_ISSET(Socket.GetSockectHandle(), &socketSet);
+ return (bIsSet != 0);
+}
+
+
+
+