1919#include "iio-private.h"
2020#include "mdns.h"
2121
22- static int new_discovery_data (struct dns_sd_discovery_data * * data )
22+ #ifdef HAVE_IPV6
23+ static const unsigned char localhost [] = {
24+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
25+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1
26+ };
27+ static const unsigned char localhost_mapped [] = {
28+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
29+ 0 , 0 , 0xff , 0xff , 0x7f , 0 , 0 , 1
30+ };
31+
32+ static bool is_localhost6 (const struct sockaddr_in6 * saddr6 )
2333{
24- struct dns_sd_discovery_data * d ;
25-
26- d = zalloc (sizeof (struct dns_sd_discovery_data ));
27- if (!d )
28- return - ENOMEM ;
34+ const uint8_t * addr = saddr6 -> sin6_addr .s6_addr ;
2935
30- * data = d ;
31- return 0 ;
36+ return ! memcmp ( addr , localhost , sizeof ( localhost )) ||
37+ ! memcmp ( addr , localhost_mapped , sizeof ( localhost_mapped )) ;
3238}
39+ #endif
3340
34- static int
35- open_client_sockets (int * sockets , int max_sockets ) {
36- // When sending, each socket can only send to one network interface
37- // Thus we need to open one socket for each interface and address family
38- int num_sockets = 0 ;
41+ static bool is_localhost4 (const struct sockaddr_in * saddr )
42+ {
43+ return saddr -> sin_addr .S_un .S_un_b .s_b1 == 127 &&
44+ saddr -> sin_addr .S_un .S_un_b .s_b2 == 0 &&
45+ saddr -> sin_addr .S_un .S_un_b .s_b3 == 0 &&
46+ saddr -> sin_addr .S_un .S_un_b .s_b4 == 1 ;
47+ }
3948
40- IP_ADAPTER_ADDRESSES * adapter_address = 0 ;
49+ static int open_client_sockets (int * sockets , unsigned int max_sockets )
50+ {
51+ IP_ADAPTER_UNICAST_ADDRESS * unicast ;
52+ IP_ADAPTER_ADDRESSES * adapter_address = 0 ;
53+ PIP_ADAPTER_ADDRESSES adapter ;
4154 ULONG address_size = 8000 ;
42- unsigned int ret ;
43- unsigned int num_retries = 4 ;
55+ unsigned int i , ret , num_retries = 4 , num_sockets = 0 ;
56+ struct sockaddr_in * saddr ;
57+ unsigned long param = 1 ;
58+ int sock ;
59+
60+ /* When sending, each socket can only send to one network interface
61+ * Thus we need to open one socket for each interface and address family */
62+
4463 do {
4564 adapter_address = malloc (address_size );
46- if (adapter_address == NULL ) {
65+ if (! adapter_address )
4766 return - ENOMEM ;
48- }
49- ret = GetAdaptersAddresses (AF_UNSPEC , GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_ANYCAST , 0 ,
50- adapter_address , & address_size );
51- if (ret == ERROR_BUFFER_OVERFLOW ) {
52- free (adapter_address );
53- adapter_address = 0 ;
54- }
55- else {
67+
68+ ret = GetAdaptersAddresses (AF_UNSPEC ,
69+ GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_ANYCAST , 0 ,
70+ adapter_address , & address_size );
71+ if (ret != ERROR_BUFFER_OVERFLOW )
5672 break ;
57- }
73+
74+ free (adapter_address );
75+ adapter_address = 0 ;
5876 } while (num_retries -- > 0 );
5977
6078 if (!adapter_address || (ret != NO_ERROR )) {
@@ -63,44 +81,36 @@ open_client_sockets(int* sockets, int max_sockets) {
6381 return num_sockets ;
6482 }
6583
66- for (PIP_ADAPTER_ADDRESSES adapter = adapter_address ; adapter ; adapter = adapter -> Next ) {
84+ for (adapter = adapter_address ; adapter ; adapter = adapter -> Next ) {
6785 if (adapter -> TunnelType == TUNNEL_TYPE_TEREDO )
6886 continue ;
6987 if (adapter -> OperStatus != IfOperStatusUp )
7088 continue ;
7189
72- for (IP_ADAPTER_UNICAST_ADDRESS * unicast = adapter -> FirstUnicastAddress ; unicast ;
73- unicast = unicast -> Next ) {
90+ for (unicast = adapter -> FirstUnicastAddress ;
91+ unicast ; unicast = unicast -> Next ) {
7492 if (unicast -> Address .lpSockaddr -> sa_family == AF_INET ) {
75- struct sockaddr_in * saddr = (struct sockaddr_in * )unicast -> Address .lpSockaddr ;
76- if ((saddr -> sin_addr .S_un .S_un_b .s_b1 != 127 ) ||
77- (saddr -> sin_addr .S_un .S_un_b .s_b2 != 0 ) ||
78- (saddr -> sin_addr .S_un .S_un_b .s_b3 != 0 ) ||
79- (saddr -> sin_addr .S_un .S_un_b .s_b4 != 1 )) {
80- if (num_sockets < max_sockets ) {
81- int sock = mdns_socket_open_ipv4 (saddr );
82- if (sock >= 0 ) {
83- sockets [num_sockets ++ ] = sock ;
84- }
85- }
93+ saddr = (struct sockaddr_in * )unicast -> Address .lpSockaddr ;
94+
95+ if (!is_localhost4 (saddr ) &&
96+ num_sockets < max_sockets ) {
97+ sock = mdns_socket_open_ipv4 (saddr );
98+ if (sock >= 0 )
99+ sockets [num_sockets ++ ] = sock ;
86100 }
87101 }
88102#ifdef HAVE_IPV6
89103 else if (unicast -> Address .lpSockaddr -> sa_family == AF_INET6 ) {
90- struct sockaddr_in6 * saddr = (struct sockaddr_in6 * )unicast -> Address .lpSockaddr ;
91- static const unsigned char localhost [] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
92- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 };
93- static const unsigned char localhost_mapped [] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
94- 0 , 0 , 0xff , 0xff , 0x7f , 0 , 0 , 1 };
95- if ((unicast -> DadState == NldsPreferred ) &&
96- memcmp (saddr -> sin6_addr .s6_addr , localhost , 16 ) &&
97- memcmp (saddr -> sin6_addr .s6_addr , localhost_mapped , 16 )) {
98- if (num_sockets < max_sockets ) {
99- int sock = mdns_socket_open_ipv6 (saddr );
100- if (sock >= 0 ) {
101- sockets [num_sockets ++ ] = sock ;
102- }
103- }
104+ struct sockaddr_in6 * saddr6 ;
105+
106+ saddr6 = (struct sockaddr_in6 * )unicast -> Address .lpSockaddr ;
107+
108+ if (unicast -> DadState == NldsPreferred &&
109+ !is_localhost6 (saddr6 ) &&
110+ num_sockets < max_sockets ) {
111+ sock = mdns_socket_open_ipv6 (saddr6 );
112+ if (sock >= 0 )
113+ sockets [num_sockets ++ ] = sock ;
104114 }
105115 }
106116#endif
@@ -109,141 +119,154 @@ open_client_sockets(int* sockets, int max_sockets) {
109119
110120 free (adapter_address );
111121
112- for (int isock = 0 ; isock < num_sockets ; ++ isock ) {
113- unsigned long param = 1 ;
114- ioctlsocket (sockets [isock ], FIONBIO , & param );
115- }
122+ for (i = 0 ; i < num_sockets ; i ++ )
123+ ioctlsocket (sockets [i ], FIONBIO , & param );
116124
117125 return num_sockets ;
118126}
119127
120128
121- static int
122- query_callback (int sock , const struct sockaddr * from , size_t addrlen ,
123- mdns_entry_type_t entry , uint16_t transaction_id ,
124- uint16_t rtype , uint16_t rclass , uint32_t ttl ,
125- const void * data , size_t size , size_t offset , size_t length ,
126- void * user_data ) {
127-
129+ static int query_callback (int sock , const struct sockaddr * from , size_t addrlen ,
130+ mdns_entry_type_t entry , uint16_t transaction_id ,
131+ uint16_t rtype , uint16_t rclass , uint32_t ttl ,
132+ const void * data , size_t size , size_t offset ,
133+ size_t length ,
134+ void * user_data )
135+ {
136+ struct dns_sd_discovery_data * dd = user_data ;
128137 char addrbuffer [64 ];
129138 char servicebuffer [64 ];
130139 char namebuffer [256 ];
140+ mdns_record_srv_t srv ;
131141
132- struct dns_sd_discovery_data * dd = (struct dns_sd_discovery_data * )user_data ;
133- if (dd == NULL ) {
142+ if (!dd ) {
134143 IIO_ERROR ("DNS SD: Missing info structure. Stop browsing.\n" );
135144 goto quit ;
136145 }
137146
138147 if (rtype != MDNS_RECORDTYPE_SRV )
139148 goto quit ;
140149
141- getnameinfo ((const struct sockaddr * )from , (socklen_t )addrlen ,
142- addrbuffer , NI_MAXHOST , servicebuffer , NI_MAXSERV ,
143- NI_NUMERICSERV | NI_NUMERICHOST );
150+ getnameinfo (from , (socklen_t )addrlen , addrbuffer , NI_MAXHOST ,
151+ servicebuffer , NI_MAXSERV , NI_NUMERICSERV | NI_NUMERICHOST );
144152
145- mdns_record_srv_t srv = mdns_record_parse_srv (data , size , offset , length ,
146- namebuffer , sizeof (namebuffer ));
147- IIO_DEBUG ("%s : SRV %.*s priority %d weight %d port %d\n" ,
148- addrbuffer ,
149- MDNS_STRING_FORMAT (srv .name ), srv .priority , srv .weight , srv .port );
153+ srv = mdns_record_parse_srv (data , size , offset , length ,
154+ namebuffer , sizeof (namebuffer ));
155+ IIO_DEBUG ("%s : SRV %.*s priority %d weight %d port %d\n" , addrbuffer ,
156+ MDNS_STRING_FORMAT (srv .name ), srv .priority , srv .weight , srv .port );
150157
151- // Go to the last element in the list
152- while (dd -> next != NULL )
158+ /* Go to the last element in the list */
159+ while (dd -> next )
153160 dd = dd -> next ;
154161
155162 if (srv .name .length > 1 )
156163 {
157164 dd -> hostname = malloc (srv .name .length );
158- if (dd -> hostname == NULL ) {
165+ if (! dd -> hostname )
159166 return - ENOMEM ;
160- }
167+
161168 iio_strlcpy (dd -> hostname , srv .name .str , srv .name .length );
162169 }
170+
163171 iio_strlcpy (dd -> addr_str , addrbuffer , DNS_SD_ADDRESS_STR_MAX );
164172 dd -> port = srv .port ;
165173
166- IIO_DEBUG ("DNS SD: added %s (%s:%d)\n" , dd -> hostname , dd -> addr_str , dd -> port );
167- // A list entry was filled, prepare new item on the list.
168- if (new_discovery_data (& dd -> next )) {
174+ IIO_DEBUG ("DNS SD: added %s (%s:%d)\n" ,
175+ dd -> hostname , dd -> addr_str , dd -> port );
176+
177+ /* A list entry was filled, prepare new item on the list */
178+ dd -> next = zalloc (sizeof (* dd -> next ));
179+ if (!dd -> next )
169180 IIO_ERROR ("DNS SD mDNS Resolver : memory failure\n" );
170- }
171181
172182quit :
173183 return 0 ;
174184}
175185
176- int dnssd_find_hosts (struct dns_sd_discovery_data * * ddata )
186+ int dnssd_find_hosts (struct dns_sd_discovery_data * * ddata )
177187{
178-
179188 WORD versionWanted = MAKEWORD (1 , 1 );
180189 WSADATA wsaData ;
190+ const char service [] = "_iio._tcp.local" ;
191+ size_t records , capacity = 2048 ;
192+ unsigned int i , isock , num_sockets ;
193+ void * buffer ;
194+ int sockets [32 ];
195+ int transaction_id [32 ];
196+ int ret ;
197+
181198 if (WSAStartup (versionWanted , & wsaData )) {
182199 printf ("Failed to initialize WinSock\n" );
183200 return -1 ;
184201 }
185202
186- struct dns_sd_discovery_data * d ;
187-
188203 IIO_DEBUG ("DNS SD: Start service discovery.\n" );
189204
190- if (new_discovery_data (& d ) < 0 ) {
205+ * ddata = zalloc (sizeof (* * ddata ));
206+ if (!* ddata )
191207 return - ENOMEM ;
192- }
193- * ddata = d ;
194208
195- size_t capacity = 2048 ;
196- void * buffer = malloc (capacity );
197- if (buffer == NULL ) {
209+
210+ buffer = malloc (capacity );
211+ if (! buffer )
198212 return - ENOMEM ;
199- }
200- const char service [] = "_iio._tcp.local" ;
201213
202214 IIO_DEBUG ("Sending DNS-SD discovery\n" );
203215
204- int sockets [32 ];
205- int transaction_id [32 ];
206- int num_sockets = open_client_sockets (sockets , sizeof (sockets ) / sizeof (sockets [0 ]));
207- if (num_sockets <= 0 ) {
216+ ret = open_client_sockets (sockets , ARRAY_SIZE (sockets ));
217+ if (ret <= 0 ) {
208218 IIO_ERROR ("Failed to open any client sockets\n" );
209- return -1 ;
219+ return ret ;
210220 }
211- IIO_DEBUG ("Opened %d socket%s for mDNS query\n" , num_sockets , num_sockets ? "s" : "" );
221+
222+ num_sockets = (unsigned int )ret ;
223+ IIO_DEBUG ("Opened %d socket%s for mDNS query\n" ,
224+ num_sockets , (num_sockets > 1 ) ? "s" : "" );
212225
213226 IIO_DEBUG ("Sending mDNS query: %s\n" , service );
214- for (int isock = 0 ; isock < num_sockets ; ++ isock ) {
215- transaction_id [isock ] = mdns_query_send (sockets [isock ], MDNS_RECORDTYPE_PTR , service , sizeof (service )- 1 , buffer ,
216- capacity );
217- if (transaction_id [isock ] <= 0 )
218- {
227+
228+ for (isock = 0 ; isock < num_sockets ; isock ++ ) {
229+ ret = mdns_query_send (sockets [isock ], MDNS_RECORDTYPE_PTR ,
230+ service , sizeof (service )- 1 , buffer ,
231+ capacity );
232+ if (ret <= 0 )
219233 IIO_ERROR ("Failed to send mDNS query: errno %d\n" , errno );
220- }
234+
235+ transaction_id [isock ] = ret ;
221236 }
222237
223- // This is a simple implementation that loops for 10 seconds or as long as we get replies
224- // A real world implementation would probably use select, poll or similar syscall to wait
225- // until data is available on a socket and then read it
238+ /* This is a simple implementation that loops for 10 seconds or as long as we get replies
239+ * A real world implementation would probably use select, poll or similar syscall to wait
240+ * until data is available on a socket and then read it */
226241 IIO_DEBUG ("Reading mDNS query replies\n" );
227- for ( int i = 0 ; i < 10 ; ++ i ) {
228- size_t records ;
242+
243+ for ( i = 0 ; i < 10 ; i ++ ) {
229244 do {
230245 records = 0 ;
231- for (int isock = 0 ; isock < num_sockets ; ++ isock ) {
232- if (transaction_id [isock ] > 0 )
233- records +=
234- mdns_query_recv (sockets [isock ], buffer , capacity , query_callback , d , transaction_id [isock ]);
246+
247+ for (isock = 0 ; isock < num_sockets ; isock ++ ) {
248+ if (transaction_id [isock ] <= 0 )
249+ continue ;
250+
251+ records += mdns_query_recv (sockets [isock ],
252+ buffer , capacity ,
253+ query_callback , * ddata ,
254+ transaction_id [isock ]);
235255 }
236256 } while (records );
257+
237258 if (records )
238259 i = 0 ;
260+
239261 Sleep (100 );
240262 }
241263
242- free (buffer );
243- for (int isock = 0 ; isock < num_sockets ; ++ isock )
264+ for (isock = 0 ; isock < num_sockets ; ++ isock )
244265 mdns_socket_close (sockets [isock ]);
245- IIO_DEBUG ("Closed socket%s\n" , num_sockets ? "s" : "" );
246266
267+ IIO_DEBUG ("Closed socket%s\n" , (num_sockets > 1 ) ? "s" : "" );
268+
269+ free (buffer );
247270 WSACleanup ();
248271
249272 return 0 ;
0 commit comments