]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/BonjourTop/source/bjsocket.cpp
mDNSResponder-1096.0.2.tar.gz
[apple/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