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, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
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 RecvAddr.sin_family = AF_INET;
124 RecvAddr.sin_port = htons( DNS_UDP_PORT );
125 RecvAddr.sin_addr.s_addr = ulAddress;
127 conn->hType = DNS_UDP;
128 memcpy( &conn->RecvAddr, &RecvAddr, sizeof( struct sockaddr_in ) );
131 return ERROR_DNS_SUCCESS;
134 /********************************************************************
135 ********************************************************************/
137 DNS_ERROR dns_open( const char *nameserver, int32 dwType,
139 struct dns_connection **conn )
143 return dns_tcp_open( nameserver, mem_ctx, conn );
145 return dns_udp_open( nameserver, mem_ctx, conn );
148 return ERROR_DNS_INVALID_PARAMETER;
151 static DNS_ERROR write_all(int fd, uint8 *data, size_t len)
155 while (total < len) {
157 ssize_t ret = write(fd, data + total, len - total);
163 return ERROR_DNS_SOCKET_ERROR;
169 return ERROR_DNS_SUCCESS;
172 static DNS_ERROR dns_send_tcp(struct dns_connection *conn,
173 const struct dns_buffer *buf)
175 uint16 len = htons(buf->offset);
178 err = write_all(conn->s, (uint8 *)&len, sizeof(len));
179 if (!ERR_DNS_IS_OK(err)) return err;
181 return write_all(conn->s, buf->data, buf->offset);
184 static DNS_ERROR dns_send_udp(struct dns_connection *conn,
185 const struct dns_buffer *buf)
189 ret = sendto(conn->s, buf->data, buf->offset, 0,
190 (struct sockaddr *)&conn->RecvAddr,
191 sizeof(conn->RecvAddr));
193 if (ret != buf->offset) {
194 return ERROR_DNS_SOCKET_ERROR;
197 return ERROR_DNS_SUCCESS;
200 DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf)
202 if (conn->hType == DNS_TCP) {
203 return dns_send_tcp(conn, buf);
206 if (conn->hType == DNS_UDP) {
207 return dns_send_udp(conn, buf);
210 return ERROR_DNS_INVALID_PARAMETER;
213 static DNS_ERROR read_all(int fd, uint8 *data, size_t len)
217 while (total < len) {
219 ssize_t ret = read(fd, data + total, len - total);
225 return ERROR_DNS_SOCKET_ERROR;
231 return ERROR_DNS_SUCCESS;
234 static DNS_ERROR dns_receive_tcp(TALLOC_CTX *mem_ctx,
235 struct dns_connection *conn,
236 struct dns_buffer **presult)
238 struct dns_buffer *buf;
242 if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
243 return ERROR_DNS_NO_MEMORY;
246 err = read_all(conn->s, (uint8 *)&len, sizeof(len));
247 if (!ERR_DNS_IS_OK(err)) {
251 buf->size = ntohs(len);
253 if (!(buf->data = TALLOC_ARRAY(buf, uint8, buf->size))) {
255 return ERROR_DNS_NO_MEMORY;
258 err = read_all(conn->s, buf->data, buf->size);
259 if (!ERR_DNS_IS_OK(err)) {
265 return ERROR_DNS_SUCCESS;
268 static DNS_ERROR dns_receive_udp(TALLOC_CTX *mem_ctx,
269 struct dns_connection *conn,
270 struct dns_buffer **presult)
272 struct dns_buffer *buf;
275 if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
276 return ERROR_DNS_NO_MEMORY;
280 * UDP based DNS can only be 512 bytes
283 if (!(buf->data = TALLOC_ARRAY(buf, uint8, 512))) {
285 return ERROR_DNS_NO_MEMORY;
288 received = recv(conn->s, (void *)buf->data, 512, 0);
290 if (received == -1) {
292 return ERROR_DNS_SOCKET_ERROR;
295 if (received > 512) {
297 return ERROR_DNS_BAD_RESPONSE;
300 buf->size = received;
304 return ERROR_DNS_SUCCESS;
307 DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
308 struct dns_buffer **presult)
310 if (conn->hType == DNS_TCP) {
311 return dns_receive_tcp(mem_ctx, conn, presult);
314 if (conn->hType == DNS_UDP) {
315 return dns_receive_udp(mem_ctx, conn, presult);
318 return ERROR_DNS_INVALID_PARAMETER;
321 DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
322 const struct dns_request *req,
323 struct dns_request **resp)
325 struct dns_buffer *buf = NULL;
328 err = dns_marshall_request(conn, req, &buf);
329 if (!ERR_DNS_IS_OK(err)) goto error;
331 err = dns_send(conn, buf);
332 if (!ERR_DNS_IS_OK(err)) goto error;
335 err = dns_receive(mem_ctx, conn, &buf);
336 if (!ERR_DNS_IS_OK(err)) goto error;
338 err = dns_unmarshall_request(mem_ctx, buf, resp);
345 DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx,
346 struct dns_connection *conn,
347 struct dns_update_request *up_req,
348 struct dns_update_request **up_resp)
350 struct dns_request *resp;
353 err = dns_transaction(mem_ctx, conn, dns_update2request(up_req),
356 if (!ERR_DNS_IS_OK(err)) return err;
358 *up_resp = dns_request2update(resp);
359 return ERROR_DNS_SUCCESS;