libaddns/dnssock.c

説明を見る。
00001 /*
00002   Linux DNS client library implementation
00003 
00004   Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
00005   Copyright (C) 2006 Gerald Carter <jerry@samba.org>
00006 
00007      ** NOTE! The following LGPL license applies to the libaddns
00008      ** library. This does NOT imply that all of Samba is released
00009      ** under the LGPL
00010 
00011   This library is free software; you can redistribute it and/or
00012   modify it under the terms of the GNU Lesser General Public
00013   License as published by the Free Software Foundation; either
00014   version 2.1 of the License, or (at your option) any later version.
00015 
00016   This library is distributed in the hope that it will be useful,
00017   but WITHOUT ANY WARRANTY; without even the implied warranty of
00018   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019   Lesser General Public License for more details.
00020 
00021   You should have received a copy of the GNU Lesser General Public
00022   License along with this library; if not, write to the Free Software
00023   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
00024   02110-1301  USA
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         /* Create a socket for sending data */
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         /* Set up the RecvAddr structure with the IP address of
00120            the receiver (in this example case "123.456.789.1")
00121            and the specified port number. */
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                          * EOF or error
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                 /* 10 second timeout */
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                         /* read timeout */
00233                         return ERROR_DNS_SOCKET_ERROR;
00234                 }
00235 
00236                 ret = read(fd, data + total, len - total);
00237                 if (ret <= 0) {
00238                         /* EOF or error */
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          * UDP based DNS can only be 512 bytes
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 }

Sambaに対してSat Aug 29 21:23:00 2009に生成されました。  doxygen 1.4.7