00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "dns.h"
00028 #include <sys/time.h>
00029 #include <unistd.h>
00030
00031 static int destroy_dns_connection(struct dns_connection *conn)
00032 {
00033 return close(conn->s);
00034 }
00035
00036
00037
00038
00039 static DNS_ERROR dns_tcp_open( const char *nameserver,
00040 TALLOC_CTX *mem_ctx,
00041 struct dns_connection **result )
00042 {
00043 uint32_t ulAddress;
00044 struct hostent *pHost;
00045 struct sockaddr_in s_in;
00046 struct dns_connection *conn;
00047 int res;
00048
00049 if (!(conn = talloc(mem_ctx, struct dns_connection))) {
00050 return ERROR_DNS_NO_MEMORY;
00051 }
00052
00053 if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
00054 if ( (pHost = gethostbyname( nameserver )) == NULL ) {
00055 TALLOC_FREE(conn);
00056 return ERROR_DNS_INVALID_NAME_SERVER;
00057 }
00058 memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
00059 }
00060
00061 conn->s = socket( PF_INET, SOCK_STREAM, 0 );
00062 if (conn->s == -1) {
00063 TALLOC_FREE(conn);
00064 return ERROR_DNS_CONNECTION_FAILED;
00065 }
00066
00067 talloc_set_destructor(conn, destroy_dns_connection);
00068
00069 s_in.sin_family = AF_INET;
00070 s_in.sin_addr.s_addr = ulAddress;
00071 s_in.sin_port = htons( DNS_TCP_PORT );
00072
00073 res = connect(conn->s, (struct sockaddr*)&s_in, sizeof( s_in ));
00074 if (res == -1) {
00075 TALLOC_FREE(conn);
00076 return ERROR_DNS_CONNECTION_FAILED;
00077 }
00078
00079 conn->hType = DNS_TCP;
00080
00081 *result = conn;
00082 return ERROR_DNS_SUCCESS;
00083 }
00084
00085
00086
00087
00088 static DNS_ERROR dns_udp_open( const char *nameserver,
00089 TALLOC_CTX *mem_ctx,
00090 struct dns_connection **result )
00091 {
00092 unsigned long ulAddress;
00093 struct hostent *pHost;
00094 struct sockaddr_in RecvAddr;
00095 struct dns_connection *conn;
00096
00097 if (!(conn = talloc(NULL, struct dns_connection))) {
00098 return ERROR_DNS_NO_MEMORY;
00099 }
00100
00101 if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
00102 if ( (pHost = gethostbyname( nameserver )) == NULL ) {
00103 TALLOC_FREE(conn);
00104 return ERROR_DNS_INVALID_NAME_SERVER;
00105 }
00106 memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
00107 }
00108
00109
00110
00111 conn->s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
00112 if (conn->s == -1) {
00113 TALLOC_FREE(conn);
00114 return ERROR_DNS_CONNECTION_FAILED;
00115 }
00116
00117 talloc_set_destructor(conn, destroy_dns_connection);
00118
00119
00120
00121
00122
00123 RecvAddr.sin_family = AF_INET;
00124 RecvAddr.sin_port = htons( DNS_UDP_PORT );
00125 RecvAddr.sin_addr.s_addr = ulAddress;
00126
00127 conn->hType = DNS_UDP;
00128 memcpy( &conn->RecvAddr, &RecvAddr, sizeof( struct sockaddr_in ) );
00129
00130 *result = conn;
00131 return ERROR_DNS_SUCCESS;
00132 }
00133
00134
00135
00136
00137 DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType,
00138 TALLOC_CTX *mem_ctx,
00139 struct dns_connection **conn )
00140 {
00141 switch ( dwType ) {
00142 case DNS_TCP:
00143 return dns_tcp_open( nameserver, mem_ctx, conn );
00144 case DNS_UDP:
00145 return dns_udp_open( nameserver, mem_ctx, conn );
00146 }
00147
00148 return ERROR_DNS_INVALID_PARAMETER;
00149 }
00150
00151 static DNS_ERROR write_all(int fd, uint8 *data, size_t len)
00152 {
00153 size_t total = 0;
00154
00155 while (total < len) {
00156
00157 ssize_t ret = write(fd, data + total, len - total);
00158
00159 if (ret <= 0) {
00160
00161
00162
00163 return ERROR_DNS_SOCKET_ERROR;
00164 }
00165
00166 total += ret;
00167 }
00168
00169 return ERROR_DNS_SUCCESS;
00170 }
00171
00172 static DNS_ERROR dns_send_tcp(struct dns_connection *conn,
00173 const struct dns_buffer *buf)
00174 {
00175 uint16 len = htons(buf->offset);
00176 DNS_ERROR err;
00177
00178 err = write_all(conn->s, (uint8 *)&len, sizeof(len));
00179 if (!ERR_DNS_IS_OK(err)) return err;
00180
00181 return write_all(conn->s, buf->data, buf->offset);
00182 }
00183
00184 static DNS_ERROR dns_send_udp(struct dns_connection *conn,
00185 const struct dns_buffer *buf)
00186 {
00187 ssize_t ret;
00188
00189 ret = sendto(conn->s, buf->data, buf->offset, 0,
00190 (struct sockaddr *)&conn->RecvAddr,
00191 sizeof(conn->RecvAddr));
00192
00193 if (ret != buf->offset) {
00194 return ERROR_DNS_SOCKET_ERROR;
00195 }
00196
00197 return ERROR_DNS_SUCCESS;
00198 }
00199
00200 DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf)
00201 {
00202 if (conn->hType == DNS_TCP) {
00203 return dns_send_tcp(conn, buf);
00204 }
00205
00206 if (conn->hType == DNS_UDP) {
00207 return dns_send_udp(conn, buf);
00208 }
00209
00210 return ERROR_DNS_INVALID_PARAMETER;
00211 }
00212
00213 static DNS_ERROR read_all(int fd, uint8 *data, size_t len)
00214 {
00215 size_t total = 0;
00216 fd_set rfds;
00217 struct timeval tv;
00218
00219 while (total < len) {
00220 ssize_t ret;
00221 int fd_ready;
00222
00223 FD_ZERO( &rfds );
00224 FD_SET( fd, &rfds );
00225
00226
00227 tv.tv_sec = 10;
00228 tv.tv_usec = 0;
00229
00230 fd_ready = select( fd+1, &rfds, NULL, NULL, &tv );
00231 if ( fd_ready == 0 ) {
00232
00233 return ERROR_DNS_SOCKET_ERROR;
00234 }
00235
00236 ret = read(fd, data + total, len - total);
00237 if (ret <= 0) {
00238
00239 return ERROR_DNS_SOCKET_ERROR;
00240 }
00241
00242 total += ret;
00243 }
00244
00245 return ERROR_DNS_SUCCESS;
00246 }
00247
00248 static DNS_ERROR dns_receive_tcp(TALLOC_CTX *mem_ctx,
00249 struct dns_connection *conn,
00250 struct dns_buffer **presult)
00251 {
00252 struct dns_buffer *buf;
00253 DNS_ERROR err;
00254 uint16 len;
00255
00256 if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
00257 return ERROR_DNS_NO_MEMORY;
00258 }
00259
00260 err = read_all(conn->s, (uint8 *)&len, sizeof(len));
00261 if (!ERR_DNS_IS_OK(err)) {
00262 return err;
00263 }
00264
00265 buf->size = ntohs(len);
00266
00267 if (buf->size) {
00268 if (!(buf->data = TALLOC_ARRAY(buf, uint8, buf->size))) {
00269 TALLOC_FREE(buf);
00270 return ERROR_DNS_NO_MEMORY;
00271 }
00272 } else {
00273 buf->data = NULL;
00274 }
00275
00276 err = read_all(conn->s, buf->data, buf->size);
00277 if (!ERR_DNS_IS_OK(err)) {
00278 TALLOC_FREE(buf);
00279 return err;
00280 }
00281
00282 *presult = buf;
00283 return ERROR_DNS_SUCCESS;
00284 }
00285
00286 static DNS_ERROR dns_receive_udp(TALLOC_CTX *mem_ctx,
00287 struct dns_connection *conn,
00288 struct dns_buffer **presult)
00289 {
00290 struct dns_buffer *buf;
00291 ssize_t received;
00292
00293 if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
00294 return ERROR_DNS_NO_MEMORY;
00295 }
00296
00297
00298
00299
00300
00301 if (!(buf->data = TALLOC_ARRAY(buf, uint8, 512))) {
00302 TALLOC_FREE(buf);
00303 return ERROR_DNS_NO_MEMORY;
00304 }
00305
00306 received = recv(conn->s, (void *)buf->data, 512, 0);
00307
00308 if (received == -1) {
00309 TALLOC_FREE(buf);
00310 return ERROR_DNS_SOCKET_ERROR;
00311 }
00312
00313 if (received > 512) {
00314 TALLOC_FREE(buf);
00315 return ERROR_DNS_BAD_RESPONSE;
00316 }
00317
00318 buf->size = received;
00319 buf->offset = 0;
00320
00321 *presult = buf;
00322 return ERROR_DNS_SUCCESS;
00323 }
00324
00325 DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
00326 struct dns_buffer **presult)
00327 {
00328 if (conn->hType == DNS_TCP) {
00329 return dns_receive_tcp(mem_ctx, conn, presult);
00330 }
00331
00332 if (conn->hType == DNS_UDP) {
00333 return dns_receive_udp(mem_ctx, conn, presult);
00334 }
00335
00336 return ERROR_DNS_INVALID_PARAMETER;
00337 }
00338
00339 DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
00340 const struct dns_request *req,
00341 struct dns_request **resp)
00342 {
00343 struct dns_buffer *buf = NULL;
00344 DNS_ERROR err;
00345
00346 err = dns_marshall_request(conn, req, &buf);
00347 if (!ERR_DNS_IS_OK(err)) goto error;
00348
00349 err = dns_send(conn, buf);
00350 if (!ERR_DNS_IS_OK(err)) goto error;
00351 TALLOC_FREE(buf);
00352
00353 err = dns_receive(mem_ctx, conn, &buf);
00354 if (!ERR_DNS_IS_OK(err)) goto error;
00355
00356 err = dns_unmarshall_request(mem_ctx, buf, resp);
00357
00358 error:
00359 TALLOC_FREE(buf);
00360 return err;
00361 }
00362
00363 DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx,
00364 struct dns_connection *conn,
00365 struct dns_update_request *up_req,
00366 struct dns_update_request **up_resp)
00367 {
00368 struct dns_request *resp;
00369 DNS_ERROR err;
00370
00371 err = dns_transaction(mem_ctx, conn, dns_update2request(up_req),
00372 &resp);
00373
00374 if (!ERR_DNS_IS_OK(err)) return err;
00375
00376 *up_resp = dns_request2update(resp);
00377 return ERROR_DNS_SUCCESS;
00378 }