diff options
Diffstat (limited to 'mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.cpp')
-rw-r--r-- | mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.cpp | 384 |
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); +} + + + + |