Imported Upstream version 878.70.2
[platform/upstream/mdnsresponder.git] / mDNSMacOSX / BonjourTop / source / bjsocket.cpp
1 //
2 //  bjsocket.cpp
3 //  TestTB
4 //
5 //  Created by Terrin Eager on 10/24/12.
6 //
7 //
8 #define __APPLE_USE_RFC_2292
9
10 #include <unistd.h>
11 #include <errno.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
14 #include <sys/time.h>
15 #include <ifaddrs.h>
16 #include <net/if.h>
17
18 #include "bjsocket.h"
19 #include "bjstring.h"
20
21
22 ////////////////////////////
23 /// BJSocket
24 ///////////////////////////
25 const BJ_UINT16 BonjourPort = 5353;
26
27 BJSocket::BJSocket()
28 {
29     socketHandle = 0;
30     buffer = NULL;
31     IPVersion = 0;
32     interfaceID = 0;
33 }
34
35 BJSocket::~BJSocket()
36 {
37
38 }
39
40 bool BJSocket::Init()
41 {
42
43     socketHandle = 0;
44     buffer = (BJ_UINT8*)malloc(MAX_FRAME_SIZE);
45
46     if (buffer == NULL)
47         return false;
48
49     //Setup msghdr;
50     memset(&socketMsghdr, '\0', sizeof(socketMsghdr));
51     socketMsghdr.msg_name = &peerAddr;
52     socketMsghdr.msg_namelen = sizeof(peerAddr);
53     socketMsghdr.msg_iov = socketIovec;
54     socketMsghdr.msg_iovlen = 1;
55     socketIovec[0].iov_base = (char *) buffer;
56     socketIovec[0].iov_len = MAX_FRAME_SIZE;
57
58
59     socketMsghdr.msg_control = socketCmsghdr;
60     socketMsghdr.msg_controllen = sizeof(socketCmsghdr);
61
62     return true;
63
64 }
65
66 bool BJSocket::CreateListenerIPv4(BJString interfaceName)
67 {
68     bool bResult = true;
69     const int onoptval = 1;
70
71     if (socketHandle)
72         Close();
73
74     Init();
75
76
77     if (interfaceName.GetLength() > 0)
78         interfaceID  = if_nametoindex(interfaceName.GetBuffer());
79
80
81     socketHandle = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
82 //     socketHandle = socket(PF_INET,SOCK_DGRAM,IPPROTO_RAW);
83
84     if (-1 == setsockopt(socketHandle,SOL_SOCKET,SO_REUSEPORT,&onoptval,sizeof(onoptval)))
85     {
86         printf("setsockopt for SO_REUSEPORT failed");
87         Close();
88         return false;
89     }
90
91     JoinMulticastv4(interfaceName);
92
93     // set PktInfo to get dest address
94
95     if (-1 == setsockopt(socketHandle, IPPROTO_IP, IP_PKTINFO, &onoptval, sizeof(onoptval)))
96     {
97         printf("setsockopt for IP_PKTINFO failed");
98         Close();
99         return false;
100     }
101
102     // bind to socket
103
104     struct sockaddr_in sa;
105     memset(&sa,0,sizeof(sockaddr_in));
106     sa.sin_len = sizeof(sockaddr_in);
107     sa.sin_family = AF_INET;
108     sa.sin_addr.s_addr = INADDR_ANY;
109     sa.sin_port = htons(BonjourPort);
110
111     if (-1 == bind(socketHandle,(struct sockaddr*)&sa,sizeof(sa)))
112     {
113         printf("error in bind: %s\n",strerror(errno));
114         Close();
115         return false;
116     }
117     IPVersion = 4;
118
119     return bResult;
120 }
121
122 bool BJSocket::CreateListenerIPv6(BJString interfaceName)
123 {
124     bool bResult = true;
125     const int onoptval=1;
126
127     if (socketHandle)
128         Close();
129
130     Init();
131
132     if (interfaceName.GetLength() > 0)
133         interfaceID  = if_nametoindex(interfaceName.GetBuffer());
134
135    socketHandle = socket(PF_INET6,SOCK_DGRAM,IPPROTO_UDP);
136
137     if (-1 == setsockopt(socketHandle,SOL_SOCKET,SO_REUSEPORT,&onoptval,sizeof(onoptval)))
138     {
139         printf("setsockopt for SO_REUSEPORT failed");
140         Close();
141         return false;
142     }
143
144     JoinMulticastv6(interfaceName);
145
146     // set PktInfo to get dest address
147     if (-1 == setsockopt(socketHandle, IPPROTO_IPV6, IPV6_PKTINFO, &onoptval, sizeof(onoptval)))
148     {
149         printf("setsockopt for IP_PKTINFO failed");
150         Close();
151         return false;
152     }
153
154     // bind to socket
155     struct sockaddr_in6 sa6;
156     memset(&sa6,0,sizeof(sockaddr_in6));
157     sa6.sin6_len = sizeof(sockaddr_in6);
158     sa6.sin6_family = AF_INET6;
159     sa6.sin6_addr = in6addr_any;
160     sa6.sin6_port = htons(BonjourPort);
161
162     if (-1 == bind(socketHandle,(struct sockaddr*)&sa6,sizeof(sa6)))
163     {
164         printf("error in bind: %s\n",strerror(errno));
165         Close();
166         return false;
167     }
168     IPVersion = 6;
169
170     return bResult;
171 }
172
173 bool BJSocket::Close()
174 {
175     bool bResult = true;
176
177     if (socketHandle)
178         close(socketHandle);
179
180     socketHandle = 0;
181
182     return bResult;
183 }
184
185 int BJSocket::Read()
186 {
187     int nLength = (int) recvmsg(socketHandle, &socketMsghdr,0);
188     if (!CheckInterface())
189         return 0;
190     struct timeval tv;
191     gettimeofday(&tv, NULL);
192     m_CurrentFrame.Set(buffer-14-40-8,nLength,tv.tv_sec*1000000ll + tv.tv_usec);
193     return nLength;
194 }
195
196 BJIPAddr* BJSocket::GetSrcAddr()
197 {
198     sourceAddr.Set(&peerAddr);
199     return &sourceAddr;
200 }
201
202 BJIPAddr* BJSocket::GetDestAddr()
203 {
204
205     struct cmsghdr *cmsg;
206
207     for(cmsg = CMSG_FIRSTHDR(&socketMsghdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&socketMsghdr, cmsg))
208     {
209
210         if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO)
211         {
212             struct in_pktinfo* pPktInfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
213
214             destAddr.Set(&pPktInfo->ipi_addr);
215         }
216         if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO)
217         {
218             struct in6_pktinfo* pPktInfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
219             destAddr.Set(&pPktInfo->ipi6_addr);
220         }
221     }
222     return &destAddr;
223 }
224
225 bool BJSocket::CheckInterface()
226 {
227     if (interfaceID ==0)
228         return true;
229     struct cmsghdr *cmsg;
230
231     bool bFound = false;
232
233     for(cmsg = CMSG_FIRSTHDR(&socketMsghdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&socketMsghdr, cmsg))
234     {
235
236         if ((cmsg->cmsg_level == IPPROTO_IP) && cmsg->cmsg_type == IP_PKTINFO)
237         {
238             bFound = true;
239             struct in_pktinfo* pPktInfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
240             if (pPktInfo->ipi_ifindex == interfaceID)
241                 return true;
242             else
243             {
244                 if (pPktInfo->ipi_ifindex != 4)
245                 {
246                     sourceAddr.Set(&peerAddr);
247                     printf("address:%d %s \n",pPktInfo->ipi_ifindex,sourceAddr.GetString());
248                 }
249             }
250         }
251         if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO)
252         {
253             bFound = true;
254             struct in6_pktinfo* pPktInfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
255             if (pPktInfo->ipi6_ifindex == interfaceID)
256                 return true;
257         }
258     }
259     if (!bFound)
260          printf("PKTINFO not found \n");
261     return false;
262 }
263
264 bool BJSocket::IsMulticastPacket()
265 {
266     return GetDestAddr()->IsBonjourMulticast();
267
268 }
269
270 int BJSocket::GetSockectHandle()
271 {
272     return socketHandle;
273 }
274
275 BJ_UINT8* BJSocket::GetBuffer()
276 {
277     return buffer;
278 }
279
280 void BJSocket::JoinMulticastv4(BJString interfaceName)
281 {
282    if (interfaceName.GetLength() == 0)
283    {
284        // join Multicast group
285        struct ip_mreq imr;
286        imr.imr_multiaddr.s_addr = inet_addr( "224.0.0.251");
287        imr.imr_interface.s_addr = INADDR_ANY;
288        if (-1 == setsockopt(socketHandle, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)))
289        {
290            printf("setsockopt for IP_ADD_MEMBERSHIP failed");
291        }
292        return;
293    }
294
295     struct ifaddrs *ifa, *orig;
296
297     getifaddrs(&ifa);
298
299     orig = ifa;
300
301     for ( ; ifa; ifa = ifa->ifa_next)
302     {
303         if (interfaceName == ifa->ifa_name  && ifa->ifa_addr->sa_family == AF_INET)
304         {
305             struct sockaddr_in *ifa_addr = (struct sockaddr_in *)ifa->ifa_addr;
306             struct ip_mreq imr;
307             imr.imr_multiaddr.s_addr = inet_addr( "224.0.0.251");
308             imr.imr_interface.s_addr = ifa_addr->sin_addr.s_addr;
309             if (-1 == setsockopt(socketHandle, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)))
310             {
311                 printf("setsockopt for IP_ADD_MEMBERSHIP failed");
312             }
313         }
314     }
315
316     freeifaddrs(orig);
317
318 }
319
320 void BJSocket::JoinMulticastv6(BJString interfaceName)
321 {
322
323     if (interfaceName.GetLength() == 0)
324         return;
325
326     // join Multicast group
327     struct in6_addr BonjourMultiaddr = {{{ 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB }}};
328     struct ipv6_mreq i6mr;
329     memset(&i6mr,0,sizeof(i6mr));
330     memcpy(&i6mr.ipv6mr_multiaddr, &BonjourMultiaddr, sizeof(BonjourMultiaddr));
331     if (interfaceName.GetLength() > 0)
332         i6mr.ipv6mr_interface = interfaceID;
333     else
334         i6mr.ipv6mr_interface = __IPV6_ADDR_SCOPE_SITELOCAL;
335     int err = setsockopt(socketHandle, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr));
336     if (err < 0 && (errno != EADDRINUSE))
337     {
338         printf("setsockopt for IPV6_JOIN_GROUP failed %d",errno);
339     }
340 }
341
342 ////////////////////////////////////////
343 // BJSelect
344 ///////////////////////////////////////
345
346
347 BJSelect::BJSelect()
348 {
349     FD_ZERO(&socketSet);
350     maxSocket = 0;
351
352 }
353
354 bool BJSelect::Add(BJSocket& s)
355 {
356     int sock = s.GetSockectHandle();
357     FD_SET(sock, &socketSet);
358     if (sock > maxSocket)
359         maxSocket = sock;
360
361     return true;
362
363 }
364
365 int BJSelect::Wait(int sec)
366 {
367     struct timeval tv;
368     memset(&tv, 0, sizeof(tv));
369     tv.tv_sec = sec;
370
371     int result = select(maxSocket+1, &socketSet, NULL, NULL, &tv);
372     return result;
373
374 }
375
376 bool BJSelect::IsReady(BJSocket& Socket)
377 {
378     int bIsSet = FD_ISSET(Socket.GetSockectHandle(), &socketSet);
379     return (bIsSet != 0);
380 }
381
382
383
384