diff options
Diffstat (limited to 'rfc1035/rfc1035udp.c')
| -rw-r--r-- | rfc1035/rfc1035udp.c | 202 |
1 files changed, 168 insertions, 34 deletions
diff --git a/rfc1035/rfc1035udp.c b/rfc1035/rfc1035udp.c index 29dac33..2a4ed34 100644 --- a/rfc1035/rfc1035udp.c +++ b/rfc1035/rfc1035udp.c @@ -40,7 +40,86 @@ int rfc1035_send_udp(int fd, const struct sockaddr *sin, int sin_len, return (-1); } -static int dorecv(int fd, char *bufptr, int buflen, int flags, +static struct rfc1035_udp_query_responses * +rfc1035_udp_query_response_alloc_common(int n_queries) +{ + struct rfc1035_udp_query_response *buf= + calloc(n_queries, sizeof(struct rfc1035_udp_query_response)); + + struct rfc1035_udp_query_responses *resps; + + if (!buf) + return 0; + + resps=malloc(sizeof(struct rfc1035_udp_query_responses)); + + if (!resps) + { + free(buf); + return 0; + } + resps->n_queries=n_queries; + resps->queries=buf; + + return resps; +} + +struct rfc1035_udp_query_responses * +rfc1035_udp_query_response_alloc(const char **queries, + const unsigned *querylens, + int n_queries) +{ + struct rfc1035_udp_query_responses *resps = + rfc1035_udp_query_response_alloc_common(n_queries); + + if (!resps) + return 0; + + for (int n=0; n<n_queries; ++n) + { + resps->queries[n].query=queries[n]; + resps->queries[n].querylen=querylens[n]; + } + + return resps; +} + + +struct rfc1035_udp_query_responses * +rfc1035_udp_query_response_alloc_bis(struct querybuf *queries, + int n_queries) +{ + struct rfc1035_udp_query_responses *resps = + rfc1035_udp_query_response_alloc_common(n_queries); + + if (!resps) + return 0; + + + for (int n=0; n<n_queries; ++n) + { + resps->queries[n].query=queries[n].qbuf; + resps->queries[n].querylen=queries[n].qbuflen; + } + + return resps; +} + +void rfc1035_udp_query_response_free(struct rfc1035_udp_query_responses *resps) +{ + int n; + + for (n=0; n<resps->n_queries; ++n) + { + if (resps->queries[n].response) + free(resps->queries[n].response); + } + + free(resps->queries); + free(resps); +} + +static int dorecv(int fd, char *bufptr, unsigned buflen, int flags, struct sockaddr *addr, socklen_t *addrlen) { socklen_t len; @@ -52,9 +131,9 @@ socklen_t len; return (len); } -char *rfc1035_recv_udp(int fd, +static int rfc1035_recv_one_udp_response(int fd, const struct sockaddr *addrshouldfrom, int addrshouldfrom_len, - int *buflen, const char *query) + struct rfc1035_udp_query_responses *queries) { int len; @@ -72,23 +151,23 @@ socklen_t addrfromlen; char rfc1035_buf[512]; char *bufptr=rfc1035_buf; char *mallocedbuf=0; +int i; +unsigned buflen=sizeof(rfc1035_buf); - *buflen=sizeof(rfc1035_buf); - - while ((len=dorecv(fd, bufptr, *buflen, MSG_PEEK, 0, 0)) >= *buflen ) + while ((len=dorecv(fd, bufptr, buflen, MSG_PEEK, 0, 0)) >= buflen ) { - if (len == *buflen) len += 511; + if (len == buflen) len += 511; ++len; if (mallocedbuf) free(mallocedbuf); mallocedbuf=(char *)malloc(len); if (!mallocedbuf) return (0); bufptr= mallocedbuf; - *buflen=len; + buflen=len; } addrfromlen=sizeof(addrfrom); - if (len < 0 || (len=dorecv(fd, bufptr, *buflen, 0, + if (len < 0 || (len=dorecv(fd, bufptr, buflen, 0, (struct sockaddr *)&addrfrom, &addrfromlen)) < 0) { if (mallocedbuf) @@ -97,7 +176,7 @@ char *mallocedbuf=0; return (0); } - *buflen=len; + buflen=len; if ( !rfc1035_same_ip( &addrfrom, addrfromlen, addrshouldfrom, addrshouldfrom_len)) @@ -109,56 +188,111 @@ char *mallocedbuf=0; return (0); } - if ( *buflen < 2) - { - if (mallocedbuf) - free(mallocedbuf); - errno=EIO; - return (0); - } - - if ( query && (bufptr[0] != query[0] || bufptr[1] != query[1] - || (unsigned char)(bufptr[2] & 0x80) == 0 )) + if ( buflen < 2) { if (mallocedbuf) free(mallocedbuf); errno=EAGAIN; return (0); } - if (!mallocedbuf) + + for (i=0; i<queries->n_queries; ++i) { - if ((mallocedbuf=malloc( *buflen )) == 0) - return (0); + if (queries->queries[i].response) + continue; /* Already received this one */ + + if ( bufptr[0] != queries->queries[i].query[0] || + bufptr[1] != queries->queries[i].query[1] + || (unsigned char)(bufptr[2] & 0x80) == 0 ) + continue; + + if (!mallocedbuf) + { + if ((mallocedbuf=malloc( buflen )) == 0) + return (0); - memcpy(mallocedbuf, bufptr, *buflen); - bufptr=mallocedbuf; + memcpy(mallocedbuf, bufptr, buflen); + bufptr=mallocedbuf; + } + + queries->queries[i].response=mallocedbuf; + queries->queries[i].resplen=buflen; + return 1; } - return (bufptr); + + if (mallocedbuf) + free(mallocedbuf); + errno=EAGAIN; + return (0); } char *rfc1035_query_udp(struct rfc1035_res *res, int fd, const struct sockaddr *sin, int sin_len, const char *query, unsigned query_len, int *buflen, unsigned w) { + struct rfc1035_udp_query_responses *resps= + rfc1035_udp_query_response_alloc(&query, &query_len, 1); + char *bufptr=0; + + if (!resps) + return 0; + + if (rfc1035_udp_query_multi(res, fd, sin, sin_len, resps, w)) + { + bufptr=resps->queries[0].response; + *buflen=resps->queries[0].resplen; + resps->queries[0].response=0; + } + + rfc1035_udp_query_response_free(resps); + return bufptr; +} + +int rfc1035_udp_query_multi(struct rfc1035_res *res, + int fd, const struct sockaddr *sin, int sin_len, + struct rfc1035_udp_query_responses *qr, + unsigned w) +{ time_t current_time, final_time; -char *rc; +int i; time(¤t_time); - if (rfc1035_send_udp(fd, sin, sin_len, query, query_len)) - return (0); + for (i=0; i<qr->n_queries; ++i) + { + if (qr->queries[i].response) + continue; /* Already sent it */ + if (rfc1035_send_udp(fd, sin, sin_len, + qr->queries[i].query, + qr->queries[i].querylen)) + return (0); + } final_time=current_time+w; - while (current_time < final_time) + while (1) { - if (rfc1035_wait_reply(fd, final_time-current_time)) + for (i=0; i<qr->n_queries; ++i) + if (!qr->queries[i].response) + break; + + if (i == qr->n_queries) + return 1; /* Everything received */ + + if (current_time >= final_time) break; - rc=rfc1035_recv_udp(fd, sin, sin_len, buflen, query); - if (rc) return (rc); + if (rfc1035_wait_reply(fd, final_time-current_time)) + break; - if (errno != EAGAIN) break; + if (!rfc1035_recv_one_udp_response(fd, + sin, + sin_len, + qr)) + { + if (errno != EAGAIN) + return 0; + } time(¤t_time); } |
