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) {
225
/* 10 second timeout */
229
fd_ready = select( fd+1, &rfds, NULL, NULL, &tv );
230
if ( fd_ready == 0 ) {
232
return ERROR_DNS_SOCKET_ERROR;
235
ret = read(fd, data + total, len - total);
238
return ERROR_DNS_SOCKET_ERROR;
244
return ERROR_DNS_SUCCESS;
247
static DNS_ERROR dns_receive_tcp(TALLOC_CTX *mem_ctx,
248
struct dns_connection *conn,
249
struct dns_buffer **presult)
251
struct dns_buffer *buf;
255
if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
256
return ERROR_DNS_NO_MEMORY;
259
err = read_all(conn->s, (uint8 *)&len, sizeof(len));
260
if (!ERR_DNS_IS_OK(err)) {
264
buf->size = ntohs(len);
267
if (!(buf->data = TALLOC_ARRAY(buf, uint8, buf->size))) {
269
return ERROR_DNS_NO_MEMORY;
275
err = read_all(conn->s, buf->data, buf->size);
276
if (!ERR_DNS_IS_OK(err)) {
282
return ERROR_DNS_SUCCESS;
285
static DNS_ERROR dns_receive_udp(TALLOC_CTX *mem_ctx,
286
struct dns_connection *conn,
287
struct dns_buffer **presult)
289
struct dns_buffer *buf;
292
if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
293
return ERROR_DNS_NO_MEMORY;
297
* UDP based DNS can only be 512 bytes
300
if (!(buf->data = TALLOC_ARRAY(buf, uint8, 512))) {
302
return ERROR_DNS_NO_MEMORY;
305
received = recv(conn->s, (void *)buf->data, 512, 0);
307
if (received == -1) {
309
return ERROR_DNS_SOCKET_ERROR;
312
if (received > 512) {
314
return ERROR_DNS_BAD_RESPONSE;
317
buf->size = received;
321
return ERROR_DNS_SUCCESS;
324
DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
325
struct dns_buffer **presult)
327
if (conn->hType == DNS_TCP) {
328
return dns_receive_tcp(mem_ctx, conn, presult);
331
if (conn->hType == DNS_UDP) {
332
return dns_receive_udp(mem_ctx, conn, presult);
335
return ERROR_DNS_INVALID_PARAMETER;
338
DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
339
const struct dns_request *req,
340
struct dns_request **resp)
342
struct dns_buffer *buf = NULL;
345
err = dns_marshall_request(conn, req, &buf);
346
if (!ERR_DNS_IS_OK(err)) goto error;
348
err = dns_send(conn, buf);
349
if (!ERR_DNS_IS_OK(err)) goto error;
352
err = dns_receive(mem_ctx, conn, &buf);
353
if (!ERR_DNS_IS_OK(err)) goto error;
355
err = dns_unmarshall_request(mem_ctx, buf, resp);
362
DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx,
363
struct dns_connection *conn,
364
struct dns_update_request *up_req,
365
struct dns_update_request **up_resp)
367
struct dns_request *resp;
370
err = dns_transaction(mem_ctx, conn, dns_update2request(up_req),
373
if (!ERR_DNS_IS_OK(err)) return err;
375
*up_resp = dns_request2update(resp);
376
return ERROR_DNS_SUCCESS;