Back to index

courier  0.68.2
rfc1035udp.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2011 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "config.h"
00007 #include      "rfc1035.h"
00008 #include      <stdio.h>
00009 #include      <string.h>
00010 #include      "soxwrap/soxwrap.h"
00011 #include      <sys/types.h>
00012 #include      <arpa/inet.h>
00013 #include      <errno.h>
00014 #include      <stdlib.h>
00015 #if    HAVE_UNISTD_H
00016 #include      <unistd.h>
00017 #endif
00018 #if TIME_WITH_SYS_TIME
00019 #include      <sys/time.h>
00020 #include      <time.h>
00021 #else
00022 #if HAVE_SYS_TIME_H
00023 #include      <sys/time.h>
00024 #else
00025 #include      <time.h>
00026 #endif
00027 #endif
00028 
00029 int rfc1035_open_udp(int *af)
00030 {
00031        return (rfc1035_mksocket(SOCK_DGRAM, 0, af));
00032 }
00033 
00034 int rfc1035_send_udp(int fd, const struct sockaddr *sin, int sin_len,
00035        const char *query, unsigned query_len)
00036 {
00037        if (sox_sendto(fd, (const char *)query, query_len, 0,
00038               sin, sin_len) == query_len)
00039               return (0);
00040        return (-1);
00041 }
00042 
00043 static int dorecv(int fd, char *bufptr, int buflen, int flags,
00044               struct sockaddr *addr, socklen_t *addrlen)
00045 {
00046 socklen_t len;
00047 
00048        do
00049        {
00050               len=sox_recvfrom(fd, bufptr, buflen, flags, addr, addrlen);
00051        } while (len < 0 && errno == EINTR);
00052        return (len);
00053 }
00054 
00055 char *rfc1035_recv_udp(int fd,
00056        const struct sockaddr *addrshouldfrom, int addrshouldfrom_len,
00057        int *buflen, const char *query)
00058 {
00059 int    len;
00060 
00061 #if    RFC1035_IPV6
00062 
00063 struct sockaddr_storage addrfrom;
00064 
00065 #else
00066 
00067 struct sockaddr_in addrfrom;
00068 
00069 #endif
00070 
00071 socklen_t addrfromlen;
00072 char   rfc1035_buf[512];
00073 char   *bufptr=rfc1035_buf;
00074 char   *mallocedbuf=0;
00075 
00076        *buflen=sizeof(rfc1035_buf);
00077 
00078        while ((len=dorecv(fd, bufptr, *buflen, MSG_PEEK, 0, 0)) >= *buflen )
00079        {
00080               if (len == *buflen)  len += 511;
00081               ++len;
00082 
00083               if (mallocedbuf)     free(mallocedbuf);
00084               mallocedbuf=(char *)malloc(len);
00085               if (!mallocedbuf)    return (0);
00086               bufptr= mallocedbuf;
00087               *buflen=len;
00088        }
00089 
00090        addrfromlen=sizeof(addrfrom);
00091        if (len < 0 || (len=dorecv(fd, bufptr, *buflen, 0,
00092               (struct sockaddr *)&addrfrom, &addrfromlen)) < 0)
00093        {
00094               if (mallocedbuf)
00095                      free(mallocedbuf);
00096               errno=EIO;
00097               return (0);
00098        }
00099 
00100        *buflen=len;
00101 
00102        if ( !rfc1035_same_ip( &addrfrom, addrfromlen,
00103                             addrshouldfrom, addrshouldfrom_len))
00104        {
00105               if (mallocedbuf)
00106                      free(mallocedbuf);
00107 
00108               errno=EAGAIN;
00109               return (0);
00110        }
00111 
00112        if ( *buflen < 2)
00113        {
00114               if (mallocedbuf)
00115                      free(mallocedbuf);
00116               errno=EIO;
00117               return (0);
00118        }
00119 
00120        if ( query && (bufptr[0] != query[0] || bufptr[1] != query[1]
00121               || (unsigned char)(bufptr[2] & 0x80) == 0 ))
00122        {
00123               if (mallocedbuf)
00124                      free(mallocedbuf);
00125               errno=EAGAIN;
00126               return (0);
00127        }
00128        if (!mallocedbuf)
00129        {
00130               if ((mallocedbuf=malloc( *buflen )) == 0)
00131                      return (0);
00132 
00133               memcpy(mallocedbuf, bufptr, *buflen);
00134               bufptr=mallocedbuf;
00135        }
00136        return (bufptr);
00137 }
00138 
00139 char *rfc1035_query_udp(struct rfc1035_res *res,
00140        int fd, const struct sockaddr *sin, int sin_len,
00141        const char *query, unsigned query_len, int *buflen, unsigned w)
00142 {
00143 time_t current_time, final_time;
00144 char   *rc;
00145 
00146        time(&current_time);
00147 
00148        if (rfc1035_send_udp(fd, sin, sin_len, query, query_len))
00149               return (0);
00150 
00151        final_time=current_time+w;
00152 
00153        while (current_time < final_time)
00154        {
00155               if (rfc1035_wait_reply(fd, final_time-current_time))
00156                      break;
00157 
00158               rc=rfc1035_recv_udp(fd, sin, sin_len, buflen, query);
00159               if (rc)       return (rc);
00160 
00161               if (errno != EAGAIN) break;
00162 
00163               time(&current_time);
00164        }
00165        errno=EAGAIN;
00166        return (0);
00167 }