2
Linux DNS client library implementation
4
Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
5
Copyright (C) 2006 Gerald Carter <jerry@samba.org>
7
** NOTE! The following LGPL license applies to the libaddns
8
** library. This does NOT imply that all of Samba is released
11
This library is free software; you can redistribute it and/or
12
modify it under the terms of the GNU Lesser General Public
13
License as published by the Free Software Foundation; either
14
version 2.1 of the License, or (at your option) any later version.
16
This library is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
Lesser General Public License for more details.
21
You should have received a copy of the GNU Lesser General Public
22
License along with this library; if not, see <http://www.gnu.org/licenses/>.
29
static int destroy_dns_connection(struct dns_connection *conn)
31
return close(conn->s);
34
/********************************************************************
35
********************************************************************/
37
static DNS_ERROR dns_tcp_open( const char *nameserver,
39
struct dns_connection **result )
42
struct hostent *pHost;
43
struct sockaddr_in s_in;
44
struct dns_connection *conn;
47
if (!(conn = talloc(mem_ctx, struct dns_connection))) {
48
return ERROR_DNS_NO_MEMORY;
51
if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
52
if ( (pHost = gethostbyname( nameserver )) == NULL ) {
54
return ERROR_DNS_INVALID_NAME_SERVER;
56
memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
59
conn->s = socket( PF_INET, SOCK_STREAM, 0 );
62
return ERROR_DNS_CONNECTION_FAILED;
65
talloc_set_destructor(conn, destroy_dns_connection);
67
s_in.sin_family = AF_INET;
68
s_in.sin_addr.s_addr = ulAddress;
69
s_in.sin_port = htons( DNS_TCP_PORT );
71
res = connect(conn->s, (struct sockaddr*)&s_in, sizeof( s_in ));
74
return ERROR_DNS_CONNECTION_FAILED;
77
conn->hType = DNS_TCP;
80
return ERROR_DNS_SUCCESS;
83
/********************************************************************
84
********************************************************************/
86
static DNS_ERROR dns_udp_open( const char *nameserver,
88
struct dns_connection **result )
90
unsigned long ulAddress;
91
struct hostent *pHost;
92
struct sockaddr_in RecvAddr;
93
struct dns_connection *conn;
95
if (!(conn = talloc(NULL, struct dns_connection))) {
96
return ERROR_DNS_NO_MEMORY;
99
if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
100
if ( (pHost = gethostbyname( nameserver )) == NULL ) {
102
return ERROR_DNS_INVALID_NAME_SERVER;
104
memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
107
/* Create a socket for sending data */
109
conn->s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
112
return ERROR_DNS_CONNECTION_FAILED;
115
talloc_set_destructor(conn, destroy_dns_connection);
117
/* Set up the RecvAddr structure with the IP address of
118
the receiver (in this example case "123.456.789.1")
119
and the specified port number. */
121
ZERO_STRUCT(RecvAddr);
122
RecvAddr.sin_family = AF_INET;
123
RecvAddr.sin_port = htons( DNS_UDP_PORT );
124
RecvAddr.sin_addr.s_addr = ulAddress;
126
conn->hType = DNS_UDP;
127
memcpy( &conn->RecvAddr, &RecvAddr, sizeof( struct sockaddr_in ) );
130
return ERROR_DNS_SUCCESS;
133
/********************************************************************
134
********************************************************************/
136
DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType,
138
struct dns_connection **conn )
142
return dns_tcp_open( nameserver, mem_ctx, conn );
144
return dns_udp_open( nameserver, mem_ctx, conn );
147
return ERROR_DNS_INVALID_PARAMETER;
150
static DNS_ERROR write_all(int fd, uint8 *data, size_t len)
154
while (total < len) {
156
ssize_t ret = write(fd, data + total, len - total);
162
return ERROR_DNS_SOCKET_ERROR;
168
return ERROR_DNS_SUCCESS;
171
static DNS_ERROR dns_send_tcp(struct dns_connection *conn,
172
const struct dns_buffer *buf)
174
uint16 len = htons(buf->offset);
177
err = write_all(conn->s, (uint8 *)&len, sizeof(len));
178
if (!ERR_DNS_IS_OK(err)) return err;
180
return write_all(conn->s, buf->data, buf->offset);
183
static DNS_ERROR dns_send_udp(struct dns_connection *conn,
184
const struct dns_buffer *buf)
188
ret = sendto(conn->s, buf->data, buf->offset, 0,
189
(struct sockaddr *)&conn->RecvAddr,
190
sizeof(conn->RecvAddr));
192
if (ret != buf->offset) {
193
return ERROR_DNS_SOCKET_ERROR;
196
return ERROR_DNS_SUCCESS;
199
DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf)
201
if (conn->hType == DNS_TCP) {
202
return dns_send_tcp(conn, buf);
205
if (conn->hType == DNS_UDP) {
206
return dns_send_udp(conn, buf);
209
return ERROR_DNS_INVALID_PARAMETER;
212
static DNS_ERROR read_all(int fd, uint8 *data, size_t len)
218
while (total < len) {
222
if (fd < 0 || fd >= FD_SETSIZE) {
224
return ERROR_DNS_SOCKET_ERROR;
230
/* 10 second timeout */
234
fd_ready = select( fd+1, &rfds, NULL, NULL, &tv );
235
if ( fd_ready == 0 ) {
237
return ERROR_DNS_SOCKET_ERROR;
240
ret = read(fd, data + total, len - total);
243
return ERROR_DNS_SOCKET_ERROR;
249
return ERROR_DNS_SUCCESS;
252
static DNS_ERROR dns_receive_tcp(TALLOC_CTX *mem_ctx,
253
struct dns_connection *conn,
254
struct dns_buffer **presult)
256
struct dns_buffer *buf;
260
if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
261
return ERROR_DNS_NO_MEMORY;
264
err = read_all(conn->s, (uint8 *)&len, sizeof(len));
265
if (!ERR_DNS_IS_OK(err)) {
269
buf->size = ntohs(len);
272
if (!(buf->data = TALLOC_ARRAY(buf, uint8, buf->size))) {
274
return ERROR_DNS_NO_MEMORY;
280
err = read_all(conn->s, buf->data, buf->size);
281
if (!ERR_DNS_IS_OK(err)) {
287
return ERROR_DNS_SUCCESS;
290
static DNS_ERROR dns_receive_udp(TALLOC_CTX *mem_ctx,
291
struct dns_connection *conn,
292
struct dns_buffer **presult)
294
struct dns_buffer *buf;
297
if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
298
return ERROR_DNS_NO_MEMORY;
302
* UDP based DNS can only be 512 bytes
305
if (!(buf->data = TALLOC_ARRAY(buf, uint8, 512))) {
307
return ERROR_DNS_NO_MEMORY;
310
received = recv(conn->s, (void *)buf->data, 512, 0);
312
if (received == -1) {
314
return ERROR_DNS_SOCKET_ERROR;
317
if (received > 512) {
319
return ERROR_DNS_BAD_RESPONSE;
322
buf->size = received;
326
return ERROR_DNS_SUCCESS;
329
DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
330
struct dns_buffer **presult)
332
if (conn->hType == DNS_TCP) {
333
return dns_receive_tcp(mem_ctx, conn, presult);
336
if (conn->hType == DNS_UDP) {
337
return dns_receive_udp(mem_ctx, conn, presult);
340
return ERROR_DNS_INVALID_PARAMETER;
343
DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
344
const struct dns_request *req,
345
struct dns_request **resp)
347
struct dns_buffer *buf = NULL;
350
err = dns_marshall_request(conn, req, &buf);
351
if (!ERR_DNS_IS_OK(err)) goto error;
353
err = dns_send(conn, buf);
354
if (!ERR_DNS_IS_OK(err)) goto error;
357
err = dns_receive(mem_ctx, conn, &buf);
358
if (!ERR_DNS_IS_OK(err)) goto error;
360
err = dns_unmarshall_request(mem_ctx, buf, resp);
367
DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx,
368
struct dns_connection *conn,
369
struct dns_update_request *up_req,
370
struct dns_update_request **up_resp)
372
struct dns_request *resp;
375
err = dns_transaction(mem_ctx, conn, dns_update2request(up_req),
378
if (!ERR_DNS_IS_OK(err)) return err;
380
*up_resp = dns_request2update(resp);
381
return ERROR_DNS_SUCCESS;