Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/ldns/net.c
39478 views
1
/*
2
* net.c
3
*
4
* Network implementation
5
* All network related functions are grouped here
6
*
7
* a Net::DNS like library for C
8
*
9
* (c) NLnet Labs, 2004-2006
10
*
11
* See the file LICENSE for the license
12
*/
13
14
#include <ldns/config.h>
15
16
#include <ldns/ldns.h>
17
18
#ifdef HAVE_NETINET_IN_H
19
#include <netinet/in.h>
20
#endif
21
#ifdef HAVE_SYS_SOCKET_H
22
#include <sys/socket.h>
23
#endif
24
#ifdef HAVE_NETDB_H
25
#include <netdb.h>
26
#endif
27
#ifdef HAVE_ARPA_INET_H
28
#include <arpa/inet.h>
29
#endif
30
#include <sys/time.h>
31
#include <errno.h>
32
#include <fcntl.h>
33
#ifdef HAVE_POLL
34
#include <poll.h>
35
#endif
36
37
ldns_status
38
ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt)
39
{
40
ldns_buffer *qb;
41
ldns_status result;
42
ldns_rdf *tsig_mac = NULL;
43
44
qb = ldns_buffer_new(LDNS_MIN_BUFLEN);
45
46
if (query_pkt && ldns_pkt_tsig(query_pkt)) {
47
tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3);
48
}
49
50
if (!query_pkt ||
51
ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) {
52
result = LDNS_STATUS_ERR;
53
} else {
54
result = ldns_send_buffer(result_packet, r, qb, tsig_mac);
55
}
56
57
ldns_buffer_free(qb);
58
59
return result;
60
}
61
62
/* code from rdata.c */
63
static struct sockaddr_storage *
64
ldns_rdf2native_sockaddr_storage_port(
65
const ldns_rdf *rd, uint16_t port, size_t *size)
66
{
67
struct sockaddr_storage *data;
68
struct sockaddr_in *data_in;
69
struct sockaddr_in6 *data_in6;
70
71
data = LDNS_MALLOC(struct sockaddr_storage);
72
if (!data) {
73
return NULL;
74
}
75
/* zero the structure for portability */
76
memset(data, 0, sizeof(struct sockaddr_storage));
77
78
switch(ldns_rdf_get_type(rd)) {
79
case LDNS_RDF_TYPE_A:
80
#ifndef S_SPLINT_S
81
data->ss_family = AF_INET;
82
#endif
83
data_in = (struct sockaddr_in*) data;
84
data_in->sin_port = (in_port_t)htons(port);
85
memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd));
86
*size = sizeof(struct sockaddr_in);
87
return data;
88
case LDNS_RDF_TYPE_AAAA:
89
#ifndef S_SPLINT_S
90
data->ss_family = AF_INET6;
91
#endif
92
data_in6 = (struct sockaddr_in6*) data;
93
data_in6->sin6_port = (in_port_t)htons(port);
94
memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd));
95
*size = sizeof(struct sockaddr_in6);
96
return data;
97
default:
98
LDNS_FREE(data);
99
return NULL;
100
}
101
}
102
103
struct sockaddr_storage *
104
ldns_rdf2native_sockaddr_storage(
105
const ldns_rdf *rd, uint16_t port, size_t *size)
106
{
107
return ldns_rdf2native_sockaddr_storage_port(
108
rd, (port == 0 ? (uint16_t)LDNS_PORT : port), size);
109
}
110
111
/** best effort to set nonblocking */
112
static void
113
ldns_sock_nonblock(int sockfd)
114
{
115
#ifdef HAVE_FCNTL
116
int flag;
117
if((flag = fcntl(sockfd, F_GETFL)) != -1) {
118
flag |= O_NONBLOCK;
119
if(fcntl(sockfd, F_SETFL, flag) == -1) {
120
/* ignore error, continue blockingly */
121
}
122
}
123
#elif defined(HAVE_IOCTLSOCKET)
124
unsigned long on = 1;
125
if(ioctlsocket(sockfd, FIONBIO, &on) != 0) {
126
/* ignore error, continue blockingly */
127
}
128
#endif
129
}
130
131
/** best effort to set blocking */
132
static void
133
ldns_sock_block(int sockfd)
134
{
135
#ifdef HAVE_FCNTL
136
int flag;
137
if((flag = fcntl(sockfd, F_GETFL)) != -1) {
138
flag &= ~O_NONBLOCK;
139
if(fcntl(sockfd, F_SETFL, flag) == -1) {
140
/* ignore error, continue */
141
}
142
}
143
#elif defined(HAVE_IOCTLSOCKET)
144
unsigned long off = 0;
145
if(ioctlsocket(sockfd, FIONBIO, &off) != 0) {
146
/* ignore error, continue */
147
}
148
#endif
149
}
150
151
/** wait for a socket to become ready */
152
static int
153
ldns_sock_wait(int sockfd, struct timeval timeout, int write)
154
{
155
int ret;
156
#ifndef HAVE_POLL
157
#ifndef S_SPLINT_S
158
fd_set fds;
159
FD_ZERO(&fds);
160
FD_SET(FD_SET_T sockfd, &fds);
161
if(write)
162
ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
163
else
164
ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
165
#endif
166
#else
167
struct pollfd pfds[2];
168
169
memset(&pfds[0], 0, sizeof(pfds[0]) * 2);
170
171
pfds[0].fd = sockfd;
172
pfds[0].events = POLLIN|POLLERR;
173
174
if (write) {
175
pfds[0].events |= POLLOUT;
176
}
177
178
ret = poll(pfds, 1, (int)(timeout.tv_sec * 1000
179
+ timeout.tv_usec / 1000));
180
#endif
181
if(ret == 0)
182
/* timeout expired */
183
return 0;
184
else if(ret == -1)
185
/* error */
186
return 0;
187
return 1;
188
}
189
190
191
static int
192
ldns_tcp_connect_from(const struct sockaddr_storage *to, socklen_t tolen,
193
const struct sockaddr_storage *from, socklen_t fromlen,
194
struct timeval timeout)
195
{
196
int sockfd;
197
198
#ifndef S_SPLINT_S
199
if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM,
200
IPPROTO_TCP)) == SOCK_INVALID) {
201
return -1;
202
}
203
#endif
204
if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == SOCK_INVALID){
205
close_socket(sockfd);
206
return -1;
207
}
208
209
/* perform nonblocking connect, to be able to wait with select() */
210
ldns_sock_nonblock(sockfd);
211
if (connect(sockfd, (struct sockaddr*)to, tolen) == SOCK_INVALID) {
212
#ifndef USE_WINSOCK
213
#ifdef EINPROGRESS
214
if(errno != EINPROGRESS) {
215
#else
216
if(1) {
217
#endif
218
close_socket(sockfd);
219
return -1;
220
}
221
#else /* USE_WINSOCK */
222
if(WSAGetLastError() != WSAEINPROGRESS &&
223
WSAGetLastError() != WSAEWOULDBLOCK) {
224
close_socket(sockfd);
225
return -1;
226
}
227
#endif
228
/* error was only telling us that it would block */
229
}
230
231
/* wait(write) until connected or error */
232
while(1) {
233
int error = 0;
234
socklen_t len = (socklen_t)sizeof(error);
235
236
if(!ldns_sock_wait(sockfd, timeout, 1)) {
237
close_socket(sockfd);
238
return -1;
239
}
240
241
/* check if there is a pending error for nonblocking connect */
242
if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error,
243
&len) < 0) {
244
#ifndef USE_WINSOCK
245
error = errno; /* on solaris errno is error */
246
#else
247
error = WSAGetLastError();
248
#endif
249
}
250
#ifndef USE_WINSOCK
251
#if defined(EINPROGRESS) && defined(EWOULDBLOCK)
252
if(error == EINPROGRESS || error == EWOULDBLOCK)
253
continue; /* try again */
254
#endif
255
else if(error != 0) {
256
close_socket(sockfd);
257
/* error in errno for our user */
258
errno = error;
259
return -1;
260
}
261
#else /* USE_WINSOCK */
262
if(error == WSAEINPROGRESS)
263
continue;
264
else if(error == WSAEWOULDBLOCK)
265
continue;
266
else if(error != 0) {
267
close_socket(sockfd);
268
errno = error;
269
return -1;
270
}
271
#endif /* USE_WINSOCK */
272
/* connected */
273
break;
274
}
275
276
/* set the socket blocking again */
277
ldns_sock_block(sockfd);
278
279
return sockfd;
280
}
281
282
int
283
ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen,
284
struct timeval timeout)
285
{
286
int s = ldns_tcp_connect_from(to, tolen, NULL, 0, timeout);
287
return s > 0 ? s : 0;
288
}
289
290
int
291
ldns_tcp_connect2(const struct sockaddr_storage *to, socklen_t tolen,
292
struct timeval timeout)
293
{
294
return ldns_tcp_connect_from(to, tolen, NULL, 0, timeout);
295
}
296
297
static int
298
ldns_tcp_bgsend_from(ldns_buffer *qbin,
299
const struct sockaddr_storage *to, socklen_t tolen,
300
const struct sockaddr_storage *from, socklen_t fromlen,
301
struct timeval timeout)
302
{
303
int sockfd;
304
305
sockfd = ldns_tcp_connect_from(to, tolen, from, fromlen, timeout);
306
307
if (sockfd >= 0 && ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) {
308
close_socket(sockfd);
309
return -1;
310
}
311
312
return sockfd;
313
}
314
315
int
316
ldns_tcp_bgsend(ldns_buffer *qbin,
317
const struct sockaddr_storage *to, socklen_t tolen,
318
struct timeval timeout)
319
{
320
int s = ldns_tcp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
321
return s > 0 ? s : 0;
322
}
323
324
int
325
ldns_tcp_bgsend2(ldns_buffer *qbin,
326
const struct sockaddr_storage *to, socklen_t tolen,
327
struct timeval timeout)
328
{
329
return ldns_tcp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
330
}
331
332
/* keep in mind that in DNS tcp messages the first 2 bytes signal the
333
* amount data to expect
334
*/
335
static ldns_status
336
ldns_tcp_send_from(uint8_t **result, ldns_buffer *qbin,
337
const struct sockaddr_storage *to, socklen_t tolen,
338
const struct sockaddr_storage *from, socklen_t fromlen,
339
struct timeval timeout, size_t *answer_size)
340
{
341
int sockfd;
342
uint8_t *answer;
343
344
sockfd = ldns_tcp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
345
346
if (sockfd == -1) {
347
return LDNS_STATUS_ERR;
348
}
349
350
answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
351
close_socket(sockfd);
352
353
if (!answer) {
354
/* oops */
355
return LDNS_STATUS_NETWORK_ERR;
356
}
357
358
*result = answer;
359
return LDNS_STATUS_OK;
360
}
361
362
ldns_status
363
ldns_tcp_send(uint8_t **result, ldns_buffer *qbin,
364
const struct sockaddr_storage *to, socklen_t tolen,
365
struct timeval timeout, size_t *answer_size)
366
{
367
return ldns_tcp_send_from(result, qbin,
368
to, tolen, NULL, 0, timeout, answer_size);
369
}
370
371
int
372
ldns_udp_connect(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout))
373
{
374
int sockfd;
375
376
#ifndef S_SPLINT_S
377
if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM,
378
IPPROTO_UDP))
379
== SOCK_INVALID) {
380
return 0;
381
}
382
#endif
383
return sockfd;
384
}
385
386
int
387
ldns_udp_connect2(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout))
388
{
389
int sockfd;
390
391
#ifndef S_SPLINT_S
392
if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM,
393
IPPROTO_UDP))
394
== SOCK_INVALID) {
395
return -1;
396
}
397
#endif
398
return sockfd;
399
}
400
401
static int
402
ldns_udp_bgsend_from(ldns_buffer *qbin,
403
const struct sockaddr_storage *to , socklen_t tolen,
404
const struct sockaddr_storage *from, socklen_t fromlen,
405
struct timeval timeout)
406
{
407
int sockfd;
408
409
sockfd = ldns_udp_connect2(to, timeout);
410
411
if (sockfd == -1) {
412
return -1;
413
}
414
415
if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
416
close_socket(sockfd);
417
return -1;
418
}
419
420
if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) {
421
close_socket(sockfd);
422
return -1;
423
}
424
return sockfd;
425
}
426
427
int
428
ldns_udp_bgsend(ldns_buffer *qbin,
429
const struct sockaddr_storage *to , socklen_t tolen,
430
struct timeval timeout)
431
{
432
int s = ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
433
return s > 0 ? s : 0;
434
}
435
436
int
437
ldns_udp_bgsend2(ldns_buffer *qbin,
438
const struct sockaddr_storage *to , socklen_t tolen,
439
struct timeval timeout)
440
{
441
return ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
442
}
443
444
static ldns_status
445
ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
446
const struct sockaddr_storage *to , socklen_t tolen,
447
const struct sockaddr_storage *from, socklen_t fromlen,
448
struct timeval timeout, size_t *answer_size)
449
{
450
int sockfd;
451
uint8_t *answer;
452
453
sockfd = ldns_udp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
454
455
if (sockfd == -1) {
456
return LDNS_STATUS_SOCKET_ERROR;
457
}
458
459
/* wait for an response*/
460
if(!ldns_sock_wait(sockfd, timeout, 0)) {
461
close_socket(sockfd);
462
return LDNS_STATUS_NETWORK_ERR;
463
}
464
465
/* set to nonblocking, so if the checksum is bad, it becomes
466
* an EAGAIN error and the ldns_udp_send function does not block,
467
* but returns a 'NETWORK_ERROR' much like a timeout. */
468
ldns_sock_nonblock(sockfd);
469
470
answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
471
close_socket(sockfd);
472
473
if (!answer) {
474
/* oops */
475
return LDNS_STATUS_NETWORK_ERR;
476
}
477
478
*result = answer;
479
return LDNS_STATUS_OK;
480
}
481
482
ldns_status
483
ldns_udp_send(uint8_t **result, ldns_buffer *qbin,
484
const struct sockaddr_storage *to , socklen_t tolen,
485
struct timeval timeout, size_t *answer_size)
486
{
487
return ldns_udp_send_from(result, qbin, to, tolen, NULL, 0,
488
timeout, answer_size);
489
}
490
491
ldns_status
492
ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac)
493
{
494
uint8_t i;
495
496
struct sockaddr_storage *src = NULL;
497
size_t src_len = 0;
498
struct sockaddr_storage *ns;
499
size_t ns_len;
500
struct timeval tv_s;
501
struct timeval tv_e;
502
503
ldns_rdf **ns_array;
504
size_t *rtt;
505
ldns_pkt *reply;
506
bool all_servers_rtt_inf;
507
uint8_t retries;
508
509
uint8_t *reply_bytes = NULL;
510
size_t reply_size = 0;
511
ldns_status status, send_status;
512
513
assert(r != NULL);
514
515
status = LDNS_STATUS_OK;
516
rtt = ldns_resolver_rtt(r);
517
ns_array = ldns_resolver_nameservers(r);
518
reply = NULL;
519
ns_len = 0;
520
521
all_servers_rtt_inf = true;
522
523
if (ldns_resolver_random(r)) {
524
ldns_resolver_nameservers_randomize(r);
525
}
526
527
if(ldns_resolver_source(r)) {
528
src = ldns_rdf2native_sockaddr_storage_port(
529
ldns_resolver_source(r), 0, &src_len);
530
}
531
532
/* loop through all defined nameservers */
533
for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
534
if (rtt[i] == LDNS_RESOLV_RTT_INF) {
535
/* not reachable nameserver! */
536
continue;
537
}
538
539
/* maybe verbosity setting?
540
printf("Sending to ");
541
ldns_rdf_print(stdout, ns_array[i]);
542
printf("\n");
543
*/
544
ns = ldns_rdf2native_sockaddr_storage(ns_array[i],
545
ldns_resolver_port(r), &ns_len);
546
547
548
#ifndef S_SPLINT_S
549
if ((ns->ss_family == AF_INET) &&
550
(ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) {
551
/* not reachable */
552
LDNS_FREE(ns);
553
continue;
554
}
555
556
if ((ns->ss_family == AF_INET6) &&
557
(ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) {
558
/* not reachable */
559
LDNS_FREE(ns);
560
continue;
561
}
562
#endif
563
564
all_servers_rtt_inf = false;
565
566
gettimeofday(&tv_s, NULL);
567
568
send_status = LDNS_STATUS_ERR;
569
570
/* reply_bytes implicitly handles our error */
571
if (ldns_resolver_usevc(r)) {
572
for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
573
send_status =
574
ldns_tcp_send_from(&reply_bytes, qb,
575
ns, (socklen_t)ns_len,
576
src, (socklen_t)src_len,
577
ldns_resolver_timeout(r),
578
&reply_size);
579
if (send_status == LDNS_STATUS_OK) {
580
break;
581
}
582
}
583
} else {
584
for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
585
/* ldns_rdf_print(stdout, ns_array[i]); */
586
send_status =
587
ldns_udp_send_from(&reply_bytes, qb,
588
ns, (socklen_t)ns_len,
589
src, (socklen_t)src_len,
590
ldns_resolver_timeout(r),
591
&reply_size);
592
if (send_status == LDNS_STATUS_OK) {
593
break;
594
}
595
}
596
}
597
598
if (send_status != LDNS_STATUS_OK) {
599
ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF);
600
status = send_status;
601
}
602
603
/* obey the fail directive */
604
if (!reply_bytes) {
605
/* the current nameserver seems to have a problem, blacklist it */
606
if (ldns_resolver_fail(r)) {
607
if(src) {
608
LDNS_FREE(src);
609
}
610
LDNS_FREE(ns);
611
return LDNS_STATUS_ERR;
612
} else {
613
LDNS_FREE(ns);
614
continue;
615
}
616
}
617
618
status = ldns_wire2pkt(&reply, reply_bytes, reply_size);
619
if (status != LDNS_STATUS_OK) {
620
if(src) LDNS_FREE(src);
621
LDNS_FREE(reply_bytes);
622
LDNS_FREE(ns);
623
return status;
624
}
625
assert(reply);
626
627
LDNS_FREE(ns);
628
gettimeofday(&tv_e, NULL);
629
630
if (reply) {
631
ldns_pkt_set_querytime(reply, (uint32_t)
632
((tv_e.tv_sec - tv_s.tv_sec) * 1000) +
633
(tv_e.tv_usec - tv_s.tv_usec) / 1000);
634
ldns_pkt_set_answerfrom(reply,
635
ldns_rdf_clone(ns_array[i]));
636
ldns_pkt_set_timestamp(reply, tv_s);
637
ldns_pkt_set_size(reply, reply_size);
638
break;
639
} else {
640
if (ldns_resolver_fail(r)) {
641
/* if fail is set bail out, after the first
642
* one */
643
break;
644
}
645
}
646
647
/* wait retrans seconds... */
648
sleep((unsigned int) ldns_resolver_retrans(r));
649
}
650
651
if(src) {
652
LDNS_FREE(src);
653
}
654
if (all_servers_rtt_inf) {
655
LDNS_FREE(reply_bytes);
656
return LDNS_STATUS_RES_NO_NS;
657
}
658
#ifdef HAVE_SSL
659
if (tsig_mac && reply && reply_bytes) {
660
if (!ldns_pkt_tsig_verify(reply,
661
reply_bytes,
662
reply_size,
663
ldns_resolver_tsig_keyname(r),
664
ldns_resolver_tsig_keydata(r), tsig_mac)) {
665
status = LDNS_STATUS_CRYPTO_TSIG_BOGUS;
666
}
667
}
668
#else
669
(void)tsig_mac;
670
#endif /* HAVE_SSL */
671
672
LDNS_FREE(reply_bytes);
673
if (result) {
674
*result = reply;
675
}
676
677
return status;
678
}
679
680
ssize_t
681
ldns_tcp_send_query(ldns_buffer *qbin, int sockfd,
682
const struct sockaddr_storage *to, socklen_t tolen)
683
{
684
uint8_t *sendbuf;
685
ssize_t bytes;
686
687
/* add length of packet */
688
sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2);
689
if(!sendbuf) return 0;
690
ldns_write_uint16(sendbuf, ldns_buffer_position(qbin));
691
memcpy(sendbuf + 2, ldns_buffer_begin(qbin), ldns_buffer_position(qbin));
692
693
bytes = sendto(sockfd, (void*)sendbuf,
694
ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen);
695
696
LDNS_FREE(sendbuf);
697
698
if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) {
699
return 0;
700
}
701
return bytes;
702
}
703
704
/* don't wait for an answer */
705
ssize_t
706
ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to,
707
socklen_t tolen)
708
{
709
ssize_t bytes;
710
711
bytes = sendto(sockfd, (void*)ldns_buffer_begin(qbin),
712
ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen);
713
714
if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) {
715
return 0;
716
}
717
return bytes;
718
}
719
720
uint8_t *
721
ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from,
722
socklen_t *fromlen)
723
{
724
uint8_t *wire, *wireout;
725
ssize_t wire_size;
726
727
wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
728
if (!wire) {
729
*size = 0;
730
return NULL;
731
}
732
733
wire_size = recvfrom(sockfd, (void*)wire, LDNS_MAX_PACKETLEN, 0,
734
(struct sockaddr *)from, fromlen);
735
736
/* recvfrom can also return 0 */
737
if (wire_size == -1 || wire_size == 0) {
738
*size = 0;
739
LDNS_FREE(wire);
740
return NULL;
741
}
742
743
*size = (size_t)wire_size;
744
wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size);
745
if(!wireout) LDNS_FREE(wire);
746
747
return wireout;
748
}
749
750
uint8_t *
751
ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout)
752
{
753
uint8_t *wire;
754
uint16_t wire_size;
755
ssize_t bytes = 0, rc = 0;
756
757
wire = LDNS_XMALLOC(uint8_t, 2);
758
if (!wire) {
759
*size = 0;
760
return NULL;
761
}
762
763
while (bytes < 2) {
764
if(!ldns_sock_wait(sockfd, timeout, 0)) {
765
*size = 0;
766
LDNS_FREE(wire);
767
return NULL;
768
}
769
rc = recv(sockfd, (void*) (wire + bytes),
770
(size_t) (2 - bytes), 0);
771
if (rc == -1 || rc == 0) {
772
*size = 0;
773
LDNS_FREE(wire);
774
return NULL;
775
}
776
bytes += rc;
777
}
778
779
wire_size = ldns_read_uint16(wire);
780
781
LDNS_FREE(wire);
782
wire = LDNS_XMALLOC(uint8_t, wire_size);
783
if (!wire) {
784
*size = 0;
785
return NULL;
786
}
787
bytes = 0;
788
789
while (bytes < (ssize_t) wire_size) {
790
if(!ldns_sock_wait(sockfd, timeout, 0)) {
791
*size = 0;
792
LDNS_FREE(wire);
793
return NULL;
794
}
795
rc = recv(sockfd, (void*) (wire + bytes),
796
(size_t) (wire_size - bytes), 0);
797
if (rc == -1 || rc == 0) {
798
LDNS_FREE(wire);
799
*size = 0;
800
return NULL;
801
}
802
bytes += rc;
803
}
804
805
*size = (size_t) bytes;
806
return wire;
807
}
808
809
uint8_t *
810
ldns_tcp_read_wire(int sockfd, size_t *size)
811
{
812
uint8_t *wire;
813
uint16_t wire_size;
814
ssize_t bytes = 0, rc = 0;
815
816
wire = LDNS_XMALLOC(uint8_t, 2);
817
if (!wire) {
818
*size = 0;
819
return NULL;
820
}
821
822
while (bytes < 2) {
823
rc = recv(sockfd, (void*) (wire + bytes),
824
(size_t) (2 - bytes), 0);
825
if (rc == -1 || rc == 0) {
826
*size = 0;
827
LDNS_FREE(wire);
828
return NULL;
829
}
830
bytes += rc;
831
}
832
833
wire_size = ldns_read_uint16(wire);
834
835
LDNS_FREE(wire);
836
wire = LDNS_XMALLOC(uint8_t, wire_size);
837
if (!wire) {
838
*size = 0;
839
return NULL;
840
}
841
bytes = 0;
842
843
while (bytes < (ssize_t) wire_size) {
844
rc = recv(sockfd, (void*) (wire + bytes),
845
(size_t) (wire_size - bytes), 0);
846
if (rc == -1 || rc == 0) {
847
LDNS_FREE(wire);
848
*size = 0;
849
return NULL;
850
}
851
bytes += rc;
852
}
853
854
*size = (size_t) bytes;
855
return wire;
856
}
857
858
#ifndef S_SPLINT_S
859
ldns_rdf *
860
ldns_sockaddr_storage2rdf(const struct sockaddr_storage *sock, uint16_t *port)
861
{
862
ldns_rdf *addr;
863
struct sockaddr_in *data_in;
864
struct sockaddr_in6 *data_in6;
865
866
switch(sock->ss_family) {
867
case AF_INET:
868
data_in = (struct sockaddr_in*)sock;
869
if (port) {
870
*port = ntohs((uint16_t)data_in->sin_port);
871
}
872
addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A,
873
LDNS_IP4ADDRLEN, &data_in->sin_addr);
874
break;
875
case AF_INET6:
876
data_in6 = (struct sockaddr_in6*)sock;
877
if (port) {
878
*port = ntohs((uint16_t)data_in6->sin6_port);
879
}
880
addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA,
881
LDNS_IP6ADDRLEN, &data_in6->sin6_addr);
882
break;
883
default:
884
if (port) {
885
*port = 0;
886
}
887
return NULL;
888
}
889
return addr;
890
}
891
#endif
892
893
/* code from resolver.c */
894
ldns_status
895
ldns_axfr_start(ldns_resolver *resolver, const ldns_rdf *domain, ldns_rr_class class)
896
{
897
ldns_pkt *query;
898
ldns_buffer *query_wire;
899
900
struct sockaddr_storage *src = NULL;
901
size_t src_len = 0;
902
struct sockaddr_storage *ns = NULL;
903
size_t ns_len = 0;
904
size_t ns_i;
905
ldns_status status;
906
907
if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) {
908
return LDNS_STATUS_ERR;
909
}
910
911
query = ldns_pkt_query_new(ldns_rdf_clone(domain), LDNS_RR_TYPE_AXFR, class, 0);
912
913
if (!query) {
914
return LDNS_STATUS_ADDRESS_ERR;
915
}
916
if(ldns_resolver_source(resolver)) {
917
src = ldns_rdf2native_sockaddr_storage_port(
918
ldns_resolver_source(resolver), 0, &src_len);
919
}
920
/* For AXFR, we have to make the connection ourselves */
921
/* try all nameservers (which usually would mean v4 fallback if
922
* @hostname is used */
923
for (ns_i = 0;
924
ns_i < ldns_resolver_nameserver_count(resolver) &&
925
resolver->_socket == SOCK_INVALID;
926
ns_i++) {
927
if (ns != NULL) {
928
LDNS_FREE(ns);
929
}
930
ns = ldns_rdf2native_sockaddr_storage(
931
resolver->_nameservers[ns_i],
932
ldns_resolver_port(resolver), &ns_len);
933
#ifndef S_SPLINT_S
934
if ((ns->ss_family == AF_INET) &&
935
(ldns_resolver_ip6(resolver) == LDNS_RESOLV_INET6)) {
936
/* not reachable */
937
LDNS_FREE(ns);
938
ns = NULL;
939
continue;
940
}
941
942
if ((ns->ss_family == AF_INET6) &&
943
(ldns_resolver_ip6(resolver) == LDNS_RESOLV_INET)) {
944
/* not reachable */
945
LDNS_FREE(ns);
946
ns = NULL;
947
continue;
948
}
949
#endif
950
951
resolver->_socket = ldns_tcp_connect_from(
952
ns, (socklen_t)ns_len,
953
src, (socklen_t)src_len,
954
ldns_resolver_timeout(resolver));
955
}
956
if (src) {
957
LDNS_FREE(src);
958
}
959
960
if (resolver->_socket == SOCK_INVALID) {
961
ldns_pkt_free(query);
962
LDNS_FREE(ns);
963
return LDNS_STATUS_NETWORK_ERR;
964
}
965
966
#ifdef HAVE_SSL
967
if (ldns_resolver_tsig_keyname(resolver) && ldns_resolver_tsig_keydata(resolver)) {
968
status = ldns_pkt_tsig_sign(query,
969
ldns_resolver_tsig_keyname(resolver),
970
ldns_resolver_tsig_keydata(resolver),
971
300, ldns_resolver_tsig_algorithm(resolver), NULL);
972
if (status != LDNS_STATUS_OK) {
973
/* to prevent problems on subsequent calls to
974
* ldns_axfr_start we have to close the socket here! */
975
close_socket(resolver->_socket);
976
resolver->_socket = 0;
977
978
ldns_pkt_free(query);
979
LDNS_FREE(ns);
980
981
return LDNS_STATUS_CRYPTO_TSIG_ERR;
982
}
983
}
984
#endif /* HAVE_SSL */
985
986
/* Convert the query to a buffer
987
* Is this necessary?
988
*/
989
query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN);
990
if(!query_wire) {
991
ldns_pkt_free(query);
992
LDNS_FREE(ns);
993
994
close_socket(resolver->_socket);
995
996
return LDNS_STATUS_MEM_ERR;
997
}
998
status = ldns_pkt2buffer_wire(query_wire, query);
999
if (status != LDNS_STATUS_OK) {
1000
ldns_pkt_free(query);
1001
ldns_buffer_free(query_wire);
1002
LDNS_FREE(ns);
1003
1004
/* to prevent problems on subsequent calls to ldns_axfr_start
1005
* we have to close the socket here! */
1006
close_socket(resolver->_socket);
1007
resolver->_socket = 0;
1008
1009
return status;
1010
}
1011
/* Send the query */
1012
if (ldns_tcp_send_query(query_wire, resolver->_socket, ns,
1013
(socklen_t)ns_len) == 0) {
1014
ldns_pkt_free(query);
1015
ldns_buffer_free(query_wire);
1016
LDNS_FREE(ns);
1017
1018
/* to prevent problems on subsequent calls to ldns_axfr_start
1019
* we have to close the socket here! */
1020
1021
1022
close_socket(resolver->_socket);
1023
1024
return LDNS_STATUS_NETWORK_ERR;
1025
}
1026
1027
ldns_pkt_free(query);
1028
ldns_buffer_free(query_wire);
1029
LDNS_FREE(ns);
1030
1031
/*
1032
* The AXFR is done once the second SOA record is sent
1033
*/
1034
resolver->_axfr_soa_count = 0;
1035
return LDNS_STATUS_OK;
1036
}
1037
1038