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
#include "system/select.h"
31
static int destroy_dns_connection(struct dns_connection *conn)
33
return close(conn->s);
36
/********************************************************************
37
********************************************************************/
39
static DNS_ERROR dns_tcp_open( const char *nameserver,
41
struct dns_connection **result )
44
struct hostent *pHost;
45
struct sockaddr_in s_in;
46
struct dns_connection *conn;
49
if (!(conn = talloc(mem_ctx, struct dns_connection))) {
50
return ERROR_DNS_NO_MEMORY;
53
if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
54
if ( (pHost = gethostbyname( nameserver )) == NULL ) {
56
return ERROR_DNS_INVALID_NAME_SERVER;
58
memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
61
conn->s = socket( PF_INET, SOCK_STREAM, 0 );
64
return ERROR_DNS_CONNECTION_FAILED;
67
talloc_set_destructor(conn, destroy_dns_connection);
69
s_in.sin_family = AF_INET;
70
s_in.sin_addr.s_addr = ulAddress;
71
s_in.sin_port = htons( DNS_TCP_PORT );
73
res = connect(conn->s, (struct sockaddr*)&s_in, sizeof( s_in ));
76
return ERROR_DNS_CONNECTION_FAILED;
79
conn->hType = DNS_TCP;
82
return ERROR_DNS_SUCCESS;
85
/********************************************************************
86
********************************************************************/
88
static DNS_ERROR dns_udp_open( const char *nameserver,
90
struct dns_connection **result )
92
unsigned long ulAddress;
93
struct hostent *pHost;
94
struct sockaddr_in RecvAddr;
95
struct dns_connection *conn;
97
if (!(conn = talloc(NULL, struct dns_connection))) {
98
return ERROR_DNS_NO_MEMORY;
101
if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
102
if ( (pHost = gethostbyname( nameserver )) == NULL ) {
104
return ERROR_DNS_INVALID_NAME_SERVER;
106
memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
109
/* Create a socket for sending data */
111
conn->s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
114
return ERROR_DNS_CONNECTION_FAILED;
117
talloc_set_destructor(conn, destroy_dns_connection);
119
/* Set up the RecvAddr structure with the IP address of
120
the receiver (in this example case "123.456.789.1")
121
and the specified port number. */
123
ZERO_STRUCT(RecvAddr);
124
RecvAddr.sin_family = AF_INET;
125
RecvAddr.sin_port = htons( DNS_UDP_PORT );
126
RecvAddr.sin_addr.s_addr = ulAddress;
128
conn->hType = DNS_UDP;
129
memcpy( &conn->RecvAddr, &RecvAddr, sizeof( struct sockaddr_in ) );
132
return ERROR_DNS_SUCCESS;
135
/********************************************************************
136
********************************************************************/
138
DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType,
140
struct dns_connection **conn )
144
return dns_tcp_open( nameserver, mem_ctx, conn );
146
return dns_udp_open( nameserver, mem_ctx, conn );
149
return ERROR_DNS_INVALID_PARAMETER;
152
static DNS_ERROR write_all(int fd, uint8 *data, size_t len)
156
while (total < len) {
158
ssize_t ret = write(fd, data + total, len - total);
164
return ERROR_DNS_SOCKET_ERROR;
170
return ERROR_DNS_SUCCESS;
173
static DNS_ERROR dns_send_tcp(struct dns_connection *conn,
174
const struct dns_buffer *buf)
176
uint16 len = htons(buf->offset);
179
err = write_all(conn->s, (uint8 *)&len, sizeof(len));
180
if (!ERR_DNS_IS_OK(err)) return err;
182
return write_all(conn->s, buf->data, buf->offset);
185
static DNS_ERROR dns_send_udp(struct dns_connection *conn,
186
const struct dns_buffer *buf)
190
ret = sendto(conn->s, buf->data, buf->offset, 0,
191
(struct sockaddr *)&conn->RecvAddr,
192
sizeof(conn->RecvAddr));
194
if (ret != buf->offset) {
195
return ERROR_DNS_SOCKET_ERROR;
198
return ERROR_DNS_SUCCESS;
201
DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf)
203
if (conn->hType == DNS_TCP) {
204
return dns_send_tcp(conn, buf);
207
if (conn->hType == DNS_UDP) {
208
return dns_send_udp(conn, buf);
211
return ERROR_DNS_INVALID_PARAMETER;
214
static DNS_ERROR read_all(int fd, uint8 *data, size_t len)
218
while (total < len) {
225
pfd.events = POLLIN|POLLHUP;
227
fd_ready = poll(&pfd, 1, 10000);
228
if ( fd_ready == 0 ) {
230
return ERROR_DNS_SOCKET_ERROR;
233
ret = read(fd, data + total, len - total);
236
return ERROR_DNS_SOCKET_ERROR;
242
return ERROR_DNS_SUCCESS;
245
static DNS_ERROR dns_receive_tcp(TALLOC_CTX *mem_ctx,
246
struct dns_connection *conn,
247
struct dns_buffer **presult)
249
struct dns_buffer *buf;
253
if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
254
return ERROR_DNS_NO_MEMORY;
257
err = read_all(conn->s, (uint8 *)&len, sizeof(len));
258
if (!ERR_DNS_IS_OK(err)) {
262
buf->size = ntohs(len);
265
if (!(buf->data = TALLOC_ARRAY(buf, uint8, buf->size))) {
267
return ERROR_DNS_NO_MEMORY;
273
err = read_all(conn->s, buf->data, buf->size);
274
if (!ERR_DNS_IS_OK(err)) {
280
return ERROR_DNS_SUCCESS;
283
static DNS_ERROR dns_receive_udp(TALLOC_CTX *mem_ctx,
284
struct dns_connection *conn,
285
struct dns_buffer **presult)
287
struct dns_buffer *buf;
290
if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
291
return ERROR_DNS_NO_MEMORY;
295
* UDP based DNS can only be 512 bytes
298
if (!(buf->data = TALLOC_ARRAY(buf, uint8, 512))) {
300
return ERROR_DNS_NO_MEMORY;
303
received = recv(conn->s, (void *)buf->data, 512, 0);
305
if (received == -1) {
307
return ERROR_DNS_SOCKET_ERROR;
310
if (received > 512) {
312
return ERROR_DNS_BAD_RESPONSE;
315
buf->size = received;
319
return ERROR_DNS_SUCCESS;
322
DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
323
struct dns_buffer **presult)
325
if (conn->hType == DNS_TCP) {
326
return dns_receive_tcp(mem_ctx, conn, presult);
329
if (conn->hType == DNS_UDP) {
330
return dns_receive_udp(mem_ctx, conn, presult);
333
return ERROR_DNS_INVALID_PARAMETER;
336
DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
337
const struct dns_request *req,
338
struct dns_request **resp)
340
struct dns_buffer *buf = NULL;
343
err = dns_marshall_request(conn, req, &buf);
344
if (!ERR_DNS_IS_OK(err)) goto error;
346
err = dns_send(conn, buf);
347
if (!ERR_DNS_IS_OK(err)) goto error;
350
err = dns_receive(mem_ctx, conn, &buf);
351
if (!ERR_DNS_IS_OK(err)) goto error;
353
err = dns_unmarshall_request(mem_ctx, buf, resp);
360
DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx,
361
struct dns_connection *conn,
362
struct dns_update_request *up_req,
363
struct dns_update_request **up_resp)
365
struct dns_request *resp;
368
err = dns_transaction(mem_ctx, conn, dns_update2request(up_req),
371
if (!ERR_DNS_IS_OK(err)) return err;
373
*up_resp = dns_request2update(resp);
374
return ERROR_DNS_SUCCESS;