yong-stropheruby 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/sock.c ADDED
@@ -0,0 +1,911 @@
1
+ /* sock.c
2
+ ** strophe XMPP client library -- socket abstraction implementation
3
+ **
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
+ **
6
+ ** This software is provided AS-IS with no warranty, either express
7
+ ** or implied.
8
+ **
9
+ ** This software is distributed under license and may not be copied,
10
+ ** modified or distributed except as expressly authorized under the
11
+ ** terms of the license contained in the file LICENSE.txt in this
12
+ ** distribution.
13
+ */
14
+
15
+ /** @file
16
+ * Socket abstraction.
17
+ */
18
+
19
+ #include <stdio.h>
20
+ #include <stdlib.h>
21
+ #include <string.h>
22
+ #include <sys/types.h>
23
+
24
+ #ifdef _WIN32
25
+ #include <winsock2.h>
26
+ #include <ws2tcpip.h>
27
+ #include <windns.h>
28
+ #include <Iphlpapi.h>
29
+ #define snprintf _snprintf
30
+ #else
31
+ #include <errno.h>
32
+ #include <unistd.h>
33
+ #include <sys/socket.h>
34
+ #include <netinet/in.h>
35
+ #include <netdb.h>
36
+ #include <fcntl.h>
37
+ #include <arpa/nameser.h>
38
+ #include <arpa/nameser_compat.h>
39
+ #include <resolv.h>
40
+ #endif
41
+
42
+ #include "sock.h"
43
+
44
+ void sock_initialize(void)
45
+ {
46
+ #ifdef _WIN32
47
+ WSADATA wsad;
48
+ WSAStartup(0x0101, &wsad);
49
+ #endif
50
+ }
51
+
52
+ void sock_shutdown(void)
53
+ {
54
+ #ifdef _WIN32
55
+ WSACleanup();
56
+ #endif
57
+ }
58
+
59
+ int sock_error(void)
60
+ {
61
+ #ifdef _WIN32
62
+ return WSAGetLastError();
63
+ #else
64
+ return errno;
65
+ #endif
66
+ }
67
+
68
+ static int _in_progress(int error)
69
+ {
70
+ #ifdef _WIN32
71
+ return (error == WSAEWOULDBLOCK || error == WSAEINPROGRESS);
72
+ #else
73
+ return (errno == EINPROGRESS);
74
+ #endif
75
+ }
76
+
77
+ sock_t sock_connect(const char * const host, const unsigned int port)
78
+ {
79
+ sock_t sock;
80
+ char service[6];
81
+ struct addrinfo *res, *ainfo, hints;
82
+ int err;
83
+
84
+ sock = -1;
85
+
86
+ snprintf(service, 6, "%u", port);
87
+
88
+ memset(&hints, 0, sizeof(struct addrinfo));
89
+ hints.ai_family = AF_INET;
90
+ hints.ai_protocol = IPPROTO_TCP;
91
+ hints.ai_socktype = SOCK_STREAM;
92
+
93
+ if ((err = getaddrinfo(host, service, &hints, &res)) != 0)
94
+ return -1;
95
+
96
+ ainfo = res;
97
+ while (ainfo) {
98
+ if ((sock = socket(ainfo->ai_family, ainfo->ai_socktype,
99
+ ainfo->ai_protocol)) >= 0) {
100
+ sock_set_nonblocking(sock);
101
+
102
+ err = connect(sock, ainfo->ai_addr, ainfo->ai_addrlen);
103
+
104
+ if ((err == 0) || (err < 0 && _in_progress(sock_error())))
105
+ break;
106
+ }
107
+
108
+ ainfo = ainfo->ai_next;
109
+ }
110
+
111
+ if (res) freeaddrinfo(res);
112
+
113
+ return sock;
114
+ }
115
+
116
+ int sock_close(const sock_t sock)
117
+ {
118
+ #ifdef _WIN32
119
+ return closesocket(sock);
120
+ #else
121
+ return close(sock);
122
+ #endif
123
+ }
124
+
125
+ int sock_set_blocking(const sock_t sock)
126
+ {
127
+ #ifdef _WIN32
128
+ u_long block = 0;
129
+ return ioctlsocket(sock, FIONBIO, &block);
130
+ #else
131
+ return fcntl(sock, F_SETFL, 0);
132
+ #endif
133
+ }
134
+
135
+ int sock_set_nonblocking(const sock_t sock)
136
+ {
137
+ #ifdef _WIN32
138
+ u_long nonblock = 1;
139
+ return ioctlsocket(sock, FIONBIO, &nonblock);
140
+ #else
141
+ return fcntl(sock, F_SETFL, O_NONBLOCK);
142
+ #endif
143
+ }
144
+
145
+ int sock_read(const sock_t sock, void * const buff, const size_t len)
146
+ {
147
+ return recv(sock, buff, len, 0);
148
+ }
149
+
150
+ int sock_write(const sock_t sock, const void * const buff, const size_t len)
151
+ {
152
+ return send(sock, buff, len, 0);
153
+ }
154
+
155
+ int sock_is_recoverable(const int error)
156
+ {
157
+ #ifdef _WIN32
158
+ return (error == WSAEINTR || error == WSAEWOULDBLOCK ||
159
+ error == WSAEINPROGRESS);
160
+ #else
161
+ return (error == EAGAIN || error == EINTR);
162
+ #endif
163
+ }
164
+
165
+ int sock_connect_error(const sock_t sock)
166
+ {
167
+ struct sockaddr sa;
168
+ unsigned len;
169
+ char temp;
170
+
171
+ sa.sa_family = AF_INET;
172
+
173
+ len = sizeof(sa);
174
+
175
+ /* we don't actually care about the peer name, we're just checking if
176
+ * we're connected or not */
177
+ if (getpeername(sock, &sa, &len) == 0)
178
+ {
179
+ return 0;
180
+ }
181
+
182
+ /* it's possible that the error wasn't ENOTCONN, so if it wasn't,
183
+ * return that */
184
+ #ifdef _WIN32
185
+ if (sock_error() != WSAENOTCONN) return sock_error();
186
+ #else
187
+ if (sock_error() != ENOTCONN) return sock_error();
188
+ #endif
189
+
190
+ /* load the correct error into errno through error slippage */
191
+ recv(sock, &temp, 1, 0);
192
+
193
+ return sock_error();
194
+ }
195
+
196
+ struct dnsquery_header
197
+ {
198
+ unsigned short id;
199
+ unsigned char qr;
200
+ unsigned char opcode;
201
+ unsigned char aa;
202
+ unsigned char tc;
203
+ unsigned char rd;
204
+ unsigned char ra;
205
+ unsigned char z;
206
+ unsigned char rcode;
207
+ unsigned short qdcount;
208
+ unsigned short ancount;
209
+ unsigned short nscount;
210
+ unsigned short arcount;
211
+ };
212
+
213
+ struct dnsquery_question
214
+ {
215
+ char qname[1024];
216
+ unsigned short qtype;
217
+ unsigned short qclass;
218
+ };
219
+
220
+ struct dnsquery_srvrdata
221
+ {
222
+ unsigned short priority;
223
+ unsigned short weight;
224
+ unsigned short port;
225
+ char target[1024];
226
+ };
227
+
228
+ struct dnsquery_resourcerecord
229
+ {
230
+ char name[1024];
231
+ unsigned short type;
232
+ unsigned short _class;
233
+ unsigned int ttl;
234
+ unsigned short rdlength;
235
+ struct dnsquery_srvrdata rdata;
236
+ };
237
+
238
+
239
+ void netbuf_add_32bitnum(unsigned char *buf, int buflen, int *offset, unsigned int num)
240
+ {
241
+ unsigned char *start = buf + *offset;
242
+ unsigned char *p = start;
243
+
244
+ /* assuming big endian */
245
+ *p++ = (num >> 24) & 0xff;
246
+ *p++ = (num >> 16) & 0xff;
247
+ *p++ = (num >> 8) & 0xff;
248
+ *p++ = (num) & 0xff;
249
+
250
+ *offset += 4;
251
+ }
252
+
253
+ void netbuf_get_32bitnum(unsigned char *buf, int buflen, int *offset, unsigned int *num)
254
+ {
255
+ unsigned char *start = buf + *offset;
256
+ unsigned char *p = start;
257
+ *num = 0;
258
+
259
+ /* assuming big endian */
260
+ *num |= (*p++) << 24;
261
+ *num |= (*p++) << 16;
262
+ *num |= (*p++) << 8;
263
+ *num |= (*p++);
264
+
265
+ *offset += 4;
266
+ }
267
+
268
+ void netbuf_add_16bitnum(unsigned char *buf, int buflen, int *offset, unsigned short num)
269
+ {
270
+ unsigned char *start = buf + *offset;
271
+ unsigned char *p = start;
272
+
273
+ /* assuming big endian */
274
+ *p++ = (num >> 8) & 0xff;
275
+ *p++ = (num) & 0xff;
276
+
277
+ *offset += 2;
278
+ }
279
+
280
+ void netbuf_get_16bitnum(unsigned char *buf, int buflen, int *offset, unsigned short *num)
281
+ {
282
+ unsigned char *start = buf + *offset;
283
+ unsigned char *p = start;
284
+ *num = 0;
285
+
286
+ /* assuming big endian */
287
+ *num |= (*p++) << 8;
288
+ *num |= (*p++);
289
+
290
+ *offset += 2;
291
+ }
292
+
293
+ void netbuf_add_domain_name(unsigned char *buf, int buflen, int *offset,
294
+ char *name)
295
+ {
296
+ unsigned char *start = buf + *offset;
297
+ unsigned char *p = start;
298
+ unsigned char *wordstart, *wordend;
299
+
300
+ wordstart = (unsigned char *)name;
301
+
302
+ while (*wordstart)
303
+ {
304
+ int len;
305
+ wordend = wordstart;
306
+ while (*wordend && *wordend != '.')
307
+ {
308
+ wordend++;
309
+ }
310
+
311
+ len = (int)(wordend - wordstart);
312
+
313
+ if (len > 0x3F)
314
+ {
315
+ len = 0x3F;
316
+ }
317
+
318
+ *p++ = len;
319
+
320
+ while (wordstart != wordend)
321
+ {
322
+ *p++ = *wordstart++;
323
+ }
324
+
325
+ if (*wordstart == '.')
326
+ {
327
+ wordstart++;
328
+ }
329
+ }
330
+
331
+ *p++ = '\0';
332
+
333
+ *offset += p - start;
334
+ }
335
+
336
+ int calc_domain_name_size(unsigned char *buf, int buflen, int offset)
337
+ {
338
+ unsigned char *p = buf + offset;
339
+ int len = 0;
340
+
341
+ while (*p)
342
+ {
343
+ if ((*p & 0xC0) == 0xC0)
344
+ {
345
+ int newoffset = 0;
346
+ newoffset |= (*p++ & 0x3F) << 8;
347
+ newoffset |= *p;
348
+
349
+ p = buf + newoffset;
350
+ }
351
+ else
352
+ {
353
+ if (len)
354
+ {
355
+ len += 1;
356
+ }
357
+ len += *p;
358
+ p += *p + 1;
359
+ }
360
+ }
361
+
362
+ return len;
363
+ }
364
+
365
+ int netbuf_get_domain_name(unsigned char *buf, int buflen, int *offset, char *namebuf, int namebuflen)
366
+ {
367
+ unsigned char *start = buf + *offset;
368
+ unsigned char *p, *p2;
369
+ int *curroffset = offset;
370
+ int len = 0;
371
+
372
+ *namebuf = '\0';
373
+
374
+ /* measure length */
375
+ p = start;
376
+ while (*p)
377
+ {
378
+ if ((*p & 0xC0) == 0xC0)
379
+ {
380
+ int newoffset = 0;
381
+ newoffset |= (*p++ & 0x3F) << 8;
382
+ newoffset |= *p++;
383
+
384
+ p = buf + newoffset;
385
+ }
386
+ else
387
+ {
388
+ len += *p;
389
+ p += *p + 1;
390
+ }
391
+ }
392
+
393
+ if (namebuflen < len)
394
+ {
395
+ return len;
396
+ }
397
+
398
+ /* actually copy in name */
399
+ p = start;
400
+ p2 = (unsigned char *)namebuf;
401
+ while (*p)
402
+ {
403
+ if ((*p & 0xC0) == 0xC0)
404
+ {
405
+ int newoffset = 0;
406
+ newoffset |= (*p++ & 0x3F) << 8;
407
+ newoffset |= *p++;
408
+
409
+ if (curroffset)
410
+ {
411
+ *curroffset += (int)(p - start);
412
+ curroffset = NULL;
413
+ }
414
+
415
+ p = buf + newoffset;
416
+ }
417
+ else
418
+ {
419
+ int i, partlen;
420
+
421
+ if (*namebuf != '\0')
422
+ {
423
+ *p2++ = '.';
424
+ }
425
+
426
+ partlen = *p++;
427
+
428
+ for (i=0; i < partlen; i++)
429
+ {
430
+ *p2++ = *p++;
431
+ }
432
+ }
433
+ }
434
+
435
+ if (curroffset)
436
+ {
437
+ p++;
438
+ *curroffset += (int)(p - start);
439
+ curroffset = NULL;
440
+ }
441
+
442
+ *p2 = '\0';
443
+
444
+ return 0;
445
+ }
446
+
447
+ void netbuf_add_dnsquery_header(unsigned char *buf, int buflen, int *offset, struct dnsquery_header *header)
448
+ {
449
+ unsigned char *p;
450
+
451
+ netbuf_add_16bitnum(buf, buflen, offset, header->id);
452
+
453
+ p = buf + *offset;
454
+ *p++ = ((header->qr & 0x01) << 7)
455
+ | ((header->opcode & 0x0F) << 3)
456
+ | ((header->aa & 0x01) << 2)
457
+ | ((header->tc & 0x01) << 1)
458
+ | ((header->rd & 0x01));
459
+ *p++ = ((header->ra & 0x01) << 7)
460
+ | ((header->z & 0x07) << 4)
461
+ | ((header->rcode & 0x0F));
462
+ *offset += 2;
463
+
464
+ netbuf_add_16bitnum(buf, buflen, offset, header->qdcount);
465
+ netbuf_add_16bitnum(buf, buflen, offset, header->ancount);
466
+ netbuf_add_16bitnum(buf, buflen, offset, header->nscount);
467
+ netbuf_add_16bitnum(buf, buflen, offset, header->arcount);
468
+ }
469
+
470
+ void netbuf_get_dnsquery_header(unsigned char *buf, int buflen, int *offset, struct dnsquery_header *header)
471
+ {
472
+ unsigned char *p;
473
+
474
+ netbuf_get_16bitnum(buf, buflen, offset, &(header->id));
475
+
476
+ p = buf + *offset;
477
+ header->qr = (*p >> 7) & 0x01;
478
+ header->opcode = (*p >> 3) & 0x0F;
479
+ header->aa = (*p >> 2) & 0x01;
480
+ header->tc = (*p >> 1) & 0x01;
481
+ header->rd = (*p) & 0x01;
482
+ p++;
483
+ header->ra = (*p >> 7) & 0x01;
484
+ header->z = (*p >> 4) & 0x07;
485
+ header->rcode = (*p) & 0x0F;
486
+ p++;
487
+ *offset += 2;
488
+
489
+ netbuf_get_16bitnum(buf, buflen, offset, &(header->qdcount));
490
+ netbuf_get_16bitnum(buf, buflen, offset, &(header->ancount));
491
+ netbuf_get_16bitnum(buf, buflen, offset, &(header->nscount));
492
+ netbuf_get_16bitnum(buf, buflen, offset, &(header->arcount));
493
+ }
494
+
495
+ void netbuf_add_dnsquery_question(unsigned char *buf, int buflen, int *offset, struct dnsquery_question *question)
496
+ {
497
+ netbuf_add_domain_name(buf, buflen, offset, question->qname);
498
+ netbuf_add_16bitnum(buf, buflen, offset, question->qtype);
499
+ netbuf_add_16bitnum(buf, buflen, offset, question->qclass);
500
+ }
501
+
502
+ void netbuf_get_dnsquery_question(unsigned char *buf, int buflen, int *offset, struct dnsquery_question *question)
503
+ {
504
+ netbuf_get_domain_name(buf, buflen, offset, question->qname, 1024);
505
+ netbuf_get_16bitnum(buf, buflen, offset, &(question->qtype));
506
+ netbuf_get_16bitnum(buf, buflen, offset, &(question->qclass));
507
+ }
508
+
509
+ void netbuf_get_dnsquery_srvrdata(unsigned char *buf, int buflen, int *offset, struct dnsquery_srvrdata *srvrdata)
510
+ {
511
+ netbuf_get_16bitnum(buf, buflen, offset, &(srvrdata->priority));
512
+ netbuf_get_16bitnum(buf, buflen, offset, &(srvrdata->weight));
513
+ netbuf_get_16bitnum(buf, buflen, offset, &(srvrdata->port));
514
+ netbuf_get_domain_name(buf, buflen, offset, srvrdata->target, 1024);
515
+ }
516
+
517
+ void netbuf_get_dnsquery_resourcerecord(unsigned char *buf, int buflen, int *offset, struct dnsquery_resourcerecord *rr)
518
+ {
519
+ netbuf_get_domain_name(buf, buflen, offset, rr->name, 1024);
520
+ netbuf_get_16bitnum(buf, buflen, offset, &(rr->type));
521
+ netbuf_get_16bitnum(buf, buflen, offset, &(rr->_class));
522
+ netbuf_get_32bitnum(buf, buflen, offset, &(rr->ttl));
523
+ netbuf_get_16bitnum(buf, buflen, offset, &(rr->rdlength));
524
+ if (rr->type == 33) /* SRV */
525
+ {
526
+ int newoffset = *offset;
527
+ netbuf_get_dnsquery_srvrdata(buf, buflen, &newoffset, &(rr->rdata));
528
+ }
529
+ *offset += rr->rdlength;
530
+ }
531
+
532
+
533
+ int sock_srv_lookup(const char *service, const char *proto, const char *domain, char *resulttarget, int resulttargetlength, int *resultport)
534
+ {
535
+ int set = 0;
536
+ char fulldomain[2048];
537
+
538
+ snprintf(fulldomain, 2048, "_%s._%s.%s", service, proto, domain);
539
+ #ifdef _WIN32
540
+
541
+ /* try using dnsapi first */
542
+ if (!set)
543
+ {
544
+ HINSTANCE hdnsapi = NULL;
545
+
546
+ DNS_STATUS (WINAPI * pDnsQuery_A)(PCSTR, WORD, DWORD, PIP4_ARRAY, PDNS_RECORD*, PVOID*);
547
+ void (WINAPI * pDnsRecordListFree)(PDNS_RECORD, DNS_FREE_TYPE);
548
+
549
+ if (hdnsapi = LoadLibrary("dnsapi.dll")) {
550
+
551
+ pDnsQuery_A = (void *)GetProcAddress(hdnsapi, "DnsQuery_A");
552
+ pDnsRecordListFree = (void *)GetProcAddress(hdnsapi, "DnsRecordListFree");
553
+
554
+ if (pDnsQuery_A && pDnsRecordListFree) {
555
+ PDNS_RECORD dnsrecords = NULL;
556
+ DNS_STATUS error;
557
+
558
+ error = pDnsQuery_A(fulldomain, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &dnsrecords, NULL);
559
+
560
+ if (error == 0) {
561
+ PDNS_RECORD current = dnsrecords;
562
+
563
+ while (current) {
564
+ if (current->wType == DNS_TYPE_SRV) {
565
+ snprintf(resulttarget, resulttargetlength, current->Data.Srv.pNameTarget);
566
+ *resultport = current->Data.Srv.wPort;
567
+ set = 1;
568
+
569
+ current = NULL;
570
+ } else {
571
+ current = current->pNext;
572
+ }
573
+ }
574
+ }
575
+
576
+ pDnsRecordListFree(dnsrecords, DnsFreeRecordList);
577
+ }
578
+
579
+ FreeLibrary(hdnsapi);
580
+ }
581
+ }
582
+
583
+ /* if dnsapi didn't work/isn't there, try querying the dns server manually */
584
+ if (!set)
585
+ {
586
+ unsigned char buf[65536];
587
+ struct dnsquery_header header;
588
+ struct dnsquery_question question;
589
+ int offset = 0;
590
+ int addrlen;
591
+ sock_t sock;
592
+ struct sockaddr_in dnsaddr;
593
+ char dnsserverips[16][256];
594
+ int numdnsservers = 0;
595
+ int j;
596
+
597
+ /* Try getting the DNS server ips from GetNetworkParams() in iphlpapi first */
598
+ if (!numdnsservers)
599
+ {
600
+ HINSTANCE hiphlpapi = NULL;
601
+ DWORD (WINAPI * pGetNetworkParams)(PFIXED_INFO, PULONG);
602
+
603
+ if (hiphlpapi = LoadLibrary("Iphlpapi.dll"))
604
+ {
605
+ pGetNetworkParams = (void *)GetProcAddress(hiphlpapi, "GetNetworkParams");
606
+
607
+ if (pGetNetworkParams)
608
+ {
609
+ FIXED_INFO *fi;
610
+ ULONG len;
611
+ DWORD error;
612
+ char buffer[65535];
613
+
614
+ len = 65535;
615
+ fi = buffer;
616
+
617
+ if ((error = pGetNetworkParams(fi, &len)) == ERROR_SUCCESS)
618
+ {
619
+ IP_ADDR_STRING *pias = &(fi->DnsServerList);
620
+
621
+ while (pias && numdnsservers < 16)
622
+ {
623
+ strcpy(dnsserverips[numdnsservers++], pias->IpAddress.String);
624
+ pias = pias->Next;
625
+ }
626
+ }
627
+ }
628
+ }
629
+ FreeLibrary(hiphlpapi);
630
+ }
631
+
632
+ /* Next, try getting the DNS server ips from the registry */
633
+ if (!numdnsservers)
634
+ {
635
+ HKEY search;
636
+ LONG error;
637
+
638
+ error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_READ, &search);
639
+
640
+ if (error != ERROR_SUCCESS)
641
+ {
642
+ error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &search);
643
+ }
644
+
645
+ if (error == ERROR_SUCCESS)
646
+ {
647
+ char name[512];
648
+ DWORD len = 512;
649
+
650
+ error = RegQueryValueEx(search, "NameServer", NULL, NULL, (LPBYTE)name, &len);
651
+
652
+ if (error != ERROR_SUCCESS)
653
+ {
654
+ error = RegQueryValueEx(search, "DhcpNameServer", NULL, NULL, (LPBYTE)name, &len);
655
+ }
656
+
657
+ if (error == ERROR_SUCCESS)
658
+ {
659
+ char *parse = "0123456789.", *start, *end;
660
+ start = name;
661
+ end = name;
662
+ name[len] = '\0';
663
+
664
+ while (*start && numdnsservers < 16)
665
+ {
666
+ while (strchr(parse, *end))
667
+ {
668
+ end++;
669
+ }
670
+
671
+ strncpy(dnsserverips[numdnsservers++], start, end - start);
672
+
673
+ while (*end && !strchr(parse, *end))
674
+ {
675
+ end++;
676
+ }
677
+
678
+ start = end;
679
+ }
680
+ }
681
+ }
682
+
683
+ RegCloseKey(search);
684
+ }
685
+
686
+ if (!numdnsservers)
687
+ {
688
+ HKEY searchlist;
689
+ LONG error;
690
+
691
+ error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces", 0, KEY_READ, &searchlist);
692
+
693
+ if (error == ERROR_SUCCESS)
694
+ {
695
+ unsigned int i;
696
+ DWORD numinterfaces = 0;
697
+
698
+ RegQueryInfoKey(searchlist, NULL, NULL, NULL, &numinterfaces, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
699
+
700
+ for (i = 0; i < numinterfaces; i++)
701
+ {
702
+ char name[512];
703
+ DWORD len = 512;
704
+ HKEY searchentry;
705
+
706
+ RegEnumKeyEx(searchlist, i, (LPTSTR)name, &len, NULL, NULL, NULL, NULL);
707
+
708
+ if (RegOpenKeyEx(searchlist, name, 0, KEY_READ, &searchentry) == ERROR_SUCCESS)
709
+ {
710
+ if (RegQueryValueEx(searchentry, "DhcpNameServer", NULL, NULL, (LPBYTE)name, &len) == ERROR_SUCCESS)
711
+ {
712
+ char *parse = "0123456789.", *start, *end;
713
+ start = name;
714
+ end = name;
715
+ name[len] = '\0';
716
+
717
+ while (*start && numdnsservers < 16)
718
+ {
719
+ while (strchr(parse, *end))
720
+ {
721
+ end++;
722
+ }
723
+
724
+ strncpy(dnsserverips[numdnsservers++], start, end - start);
725
+
726
+ while (*end && !strchr(parse, *end))
727
+ {
728
+ end++;
729
+ }
730
+
731
+ start = end;
732
+ }
733
+ }
734
+ else if (RegQueryValueEx(searchentry, "NameServer", NULL, NULL, (LPBYTE)name, &len) == ERROR_SUCCESS)
735
+ {
736
+ char *parse = "0123456789.", *start, *end;
737
+ start = name;
738
+ end = name;
739
+ name[len] = '\0';
740
+
741
+ while (*start && numdnsservers < 16)
742
+ {
743
+ while (strchr(parse, *end))
744
+ {
745
+ end++;
746
+ }
747
+
748
+ strncpy(dnsserverips[numdnsservers++], start, end - start);
749
+
750
+ while (*end && !strchr(parse, *end))
751
+ {
752
+ end++;
753
+ }
754
+
755
+ start = end;
756
+ }
757
+ }
758
+ RegCloseKey(searchentry);
759
+ }
760
+ }
761
+ RegCloseKey(searchlist);
762
+ }
763
+ }
764
+
765
+ /* If we have a DNS server, use it */
766
+ if (numdnsservers)
767
+ {
768
+ ULONG nonblocking = 1;
769
+ int i;
770
+ int insize;
771
+
772
+ memset(&header, 0, sizeof(header));
773
+ header.id = 12345; /* FIXME: Get a better id here */
774
+ header.rd = 1;
775
+ header.qdcount = 1;
776
+
777
+ netbuf_add_dnsquery_header(buf, 65536, &offset, &header);
778
+
779
+ memset(&question, 0, sizeof(question));
780
+ strncpy(question.qname, fulldomain, 1024);
781
+ question.qtype = 33; /* SRV */
782
+ question.qclass = 1; /* INTERNET! */
783
+
784
+ netbuf_add_dnsquery_question(buf, 65536, &offset, &question);
785
+
786
+ insize = 0;
787
+ for (i = 0; i < numdnsservers && insize <= 0; i++)
788
+ {
789
+ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
790
+ ioctlsocket(sock, FIONBIO, &nonblocking);
791
+
792
+ memset(&dnsaddr, 0, sizeof(dnsaddr));
793
+
794
+ dnsaddr.sin_family = AF_INET;
795
+ dnsaddr.sin_port = htons(53);
796
+ dnsaddr.sin_addr.s_addr = inet_addr(dnsserverips[i]);
797
+
798
+ addrlen = sizeof(dnsaddr);
799
+ sendto(sock, (char *)buf, offset, 0, (struct sockaddr *)&dnsaddr, addrlen);
800
+ for (j = 0; j < 50; j++)
801
+ {
802
+ insize = recvfrom(sock, (char *)buf, 65536, 0, (struct sockaddr *)&dnsaddr, &addrlen);
803
+ if (insize == SOCKET_ERROR)
804
+ {
805
+ if (sock_error() == WSAEWOULDBLOCK)
806
+ {
807
+ Sleep(100);
808
+ }
809
+ else
810
+ {
811
+ break;
812
+ }
813
+ }
814
+ else
815
+ {
816
+ break;
817
+ }
818
+ }
819
+
820
+ closesocket(sock);
821
+ }
822
+
823
+ offset = insize;
824
+
825
+ if (offset > 0)
826
+ {
827
+ int len = offset;
828
+ int i;
829
+ struct dnsquery_header header;
830
+ struct dnsquery_question question;
831
+ struct dnsquery_resourcerecord rr;
832
+
833
+ offset = 0;
834
+ netbuf_get_dnsquery_header(buf, 65536, &offset, &header);
835
+
836
+ for (i = 0; i < header.qdcount; i++)
837
+ {
838
+ netbuf_get_dnsquery_question(buf, 65536, &offset, &question);
839
+ }
840
+
841
+ for (i = 0; i < header.ancount; i++)
842
+ {
843
+ netbuf_get_dnsquery_resourcerecord(buf, 65536, &offset, &rr);
844
+
845
+ if (rr.type == 33)
846
+ {
847
+ struct dnsquery_srvrdata *srvrdata = &(rr.rdata);
848
+
849
+ snprintf(resulttarget, resulttargetlength, srvrdata->target);
850
+ *resultport = srvrdata->port;
851
+ set = 1;
852
+ }
853
+ }
854
+
855
+ for (i = 0; i < header.ancount; i++)
856
+ {
857
+ netbuf_get_dnsquery_resourcerecord(buf, 65536, &offset, &rr);
858
+ }
859
+ }
860
+ }
861
+
862
+ }
863
+
864
+ #else
865
+ if (!set) {
866
+ unsigned char buf[65535];
867
+ int len;
868
+
869
+ if ((len = res_query(fulldomain, C_IN, T_SRV, buf, 65535)) > 0) {
870
+ int offset;
871
+ int i;
872
+ struct dnsquery_header header;
873
+ struct dnsquery_question question;
874
+ struct dnsquery_resourcerecord rr;
875
+
876
+ offset = 0;
877
+ netbuf_get_dnsquery_header(buf, 65536, &offset, &header);
878
+
879
+ for (i = 0; i < header.qdcount; i++) {
880
+ netbuf_get_dnsquery_question(buf, 65536, &offset, &question);
881
+ }
882
+
883
+ for (i = 0; i < header.ancount; i++) {
884
+ netbuf_get_dnsquery_resourcerecord(buf, 65536, &offset, &rr);
885
+
886
+ if (rr.type == 33) {
887
+ struct dnsquery_srvrdata *srvrdata = &(rr.rdata);
888
+
889
+ snprintf(resulttarget, resulttargetlength,
890
+ srvrdata->target);
891
+ *resultport = srvrdata->port;
892
+ set = 1;
893
+ }
894
+ }
895
+
896
+ for (i = 0; i < header.ancount; i++) {
897
+ netbuf_get_dnsquery_resourcerecord(buf, 65536, &offset, &rr);
898
+ }
899
+ }
900
+ }
901
+ #endif
902
+
903
+ if (!set)
904
+ {
905
+ snprintf(resulttarget, resulttargetlength, domain);
906
+ *resultport = 5222;
907
+ return 0;
908
+ }
909
+
910
+ return 1;
911
+ }