int vbuf__append_quoted1035(vbuf *vb, const byte *buf, int len) { char qbuf[10]; int i, ch; while (len) { qbuf[0]= 0; for (i=0; i<len; i++) { ch= buf[i]; if (ch <= ' ' || ch >= 127) { sprintf(qbuf,"\\%03o",ch); break; } else if (!ctype_domainunquoted(ch)) { sprintf(qbuf,"\\%c",ch); break; } } if (!adns__vbuf_append(vb,buf,i) || !adns__vbuf_append(vb,qbuf,strlen(qbuf))) return 0; if (i<len) i++; buf+= i; len-= i; } return 1; }
const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, vbuf *vb, const byte *dgram, int dglen, int cbyte) { adns_status st; st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok, dgram,dglen,&cbyte,dglen); if (st == adns_s_nomemory) { return "<cannot report domain... out of memory>"; } if (st) { vb->used= 0; if (!(adns__vbuf_appendstr(vb,"<bad format... ") && adns__vbuf_appendstr(vb,adns_strerror(st)) && adns__vbuf_appendstr(vb,">") && adns__vbuf_append(vb,"",1))) { return "<cannot report bad format... out of memory>"; } } if (!vb->used) { adns__vbuf_appendstr(vb,"<truncated ...>"); adns__vbuf_append(vb,"",1); } return vb->buf; }
adns_status adns__parse_domain_more(findlabel_state *flstate, adns_state ads, adns_query qu, vbuf *vb, parsedomain_flags flags, const byte *dgram) { int lablen, labstart, i, ch, first; adns_status st; first= 1; for (;;) { st= adns__findlabel_next(flstate,&lablen,&labstart); if (st) return st; if (lablen<0) { vb->used=0; return adns_s_ok; } if (!lablen) break; if (first) { first= 0; } else { if (!adns__vbuf_append(vb,".",1)) return adns_s_nomemory; } if (flags & pdf_quoteok) { if (!vbuf__append_quoted1035(vb,dgram+labstart,lablen)) return adns_s_nomemory; } else { ch= dgram[labstart]; if (!ctype_alpha(ch) && !ctype_digit(ch)) return adns_s_answerdomaininvalid; for (i= labstart+1; i<labstart+lablen; i++) { ch= dgram[i]; if (ch != '-' && !ctype_alpha(ch) && !ctype_digit(ch)) return adns_s_answerdomaininvalid; } if (!adns__vbuf_append(vb, (const char *) dgram+labstart,lablen)) return adns_s_nomemory; } } if (!adns__vbuf_append(vb,"",1)) return adns_s_nomemory; return adns_s_ok; }
void adns__querysend_tcp(adns_query qu, struct timeval now) { byte length[2]; #if 0 struct iovec iov[2]; #endif int wr, wr2 = 0, r; adns_state ads; if (qu->ads->tcpstate != server_ok) return; assert(qu->state == query_tcpw); length[0]= (qu->query_dglen&0x0ff00U) >>8; length[1]= (qu->query_dglen&0x0ff); ads= qu->ads; if (!adns__vbuf_ensure(&ads->tcpsend,ads->tcpsend.used+qu->query_dglen+2)) return; qu->retries++; /* Reset idle timeout. */ ads->tcptimeout.tv_sec= ads->tcptimeout.tv_usec= 0; if (ads->tcpsend.used) { wr= 0; } else { #if 0 iov[0].iov_base= (char *)length; iov[0].iov_len= 2; iov[1].iov_base= (char *)qu->query_dgram; iov[1].iov_len= qu->query_dglen; wr= writev(qu->ads->tcpsocket,iov,2); #endif wr = write(qu->ads->tcpsocket, (char *)length, 2); if (wr > 0) wr2 = write(qu->ads->tcpsocket, (char *)qu->query_dgram, qu->query_dglen); if (wr < 0 || wr2 < 0) { if (!(errno == EAGAIN || errno == EINTR || errno == ENOSPC || errno == ENOBUFS || errno == ENOMEM)) { adns__tcp_broken(ads,"write",strerror(errno)); return; } wr= 0; } } if (wr<2) { r= adns__vbuf_append(&ads->tcpsend,length,2-wr); assert(r); wr= 0; } else { wr-= 2; } if (wr<qu->query_dglen) { r= adns__vbuf_append(&ads->tcpsend,qu->query_dgram+wr,qu->query_dglen-wr); assert(r); } }
adns_status adns_rr_info(adns_rrtype type, const char **rrtname_r, const char **fmtname_r, int *len_r, const void *datap, char **data_r) { const typeinfo *typei; vbuf vb; adns_status st; typei= adns__findtype(type); if (!typei) return adns_s_unknownrrtype; if (rrtname_r) *rrtname_r= typei->rrtname; if (fmtname_r) *fmtname_r= typei->fmtname; if (len_r) *len_r= typei->rrsz; if (!datap) return adns_s_ok; adns__vbuf_init(&vb); st= typei->convstring(&vb,datap); if (st) goto x_freevb; if (!adns__vbuf_append(&vb,(byte*)"",1)) { st= adns_s_nomemory; goto x_freevb; } assert((int)strlen((char*)vb.buf) == vb.used-1); *data_r= realloc(vb.buf, (size_t) vb.used); if (!*data_r) *data_r= (char*)vb.buf; return adns_s_ok; x_freevb: adns__vbuf_free(&vb); return st; }
int Hwritev(int fd, const struct iovec *vector, size_t count) { size_t i; vbw.used= 0; for (i=0; i<count; i++, vector++) { if (!adns__vbuf_append(&vbw,vector->iov_base,vector->iov_len)) Tnomem(); } return Hwrite(fd,vbw.buf,vbw.used); }
int adns__vbuf_appendstr(vbuf *vb, const char *data) { int l; l= strlen(data); return adns__vbuf_append(vb,(byte*)data,l); }
void adns__querysend_tcp(adns_query qu, struct timeval now) { byte length[2]; #ifndef WIN32 struct iovec iov[2]; #endif int wr, r; adns_state ads; if (qu->ads->tcpstate != server_ok) return; assert(qu->state == query_tcpw); length[0] = (qu->query_dglen & 0x0ff00U) >> 8; length[1] = (qu->query_dglen & 0x0ff); ads = qu->ads; if( !adns__vbuf_ensure( &ads->tcpsend, ads->tcpsend.used + qu->query_dglen + 2 ) ) return; qu->retries++; /* Reset idle timeout. */ ads->tcptimeout.tv_sec = ads->tcptimeout.tv_usec = 0; if (ads->tcpsend.used) { wr = 0; } else { #ifdef WIN32 char *buf = NULL; buf = (char *)ns_malloc((2 + qu->query_dglen)); os_memcpy(buf, length, 2); os_memcpy((buf + 2), qu->query_dgram, qu->query_dglen); wr = os_sock_write(qu->ads->tcpsocket, buf, (2 + qu->query_dglen)); errno = os_sock_errno; ns_free(buf); #else iov[0].iov_base = length; iov[0].iov_len = 2; iov[1].iov_base = qu->query_dgram; iov[1].iov_len = qu->query_dglen; adns__sigpipe_protect(qu->ads); wr = writev(qu->ads->tcpsocket, iov, 2); #endif adns__sigpipe_unprotect(qu->ads); if (wr < 0) { if (! (errno == EAGAIN || errno == OS_SOCK_EINTR || errno == ENOSPC || errno == OS_SOCK_ENOBUFS || errno == ENOMEM)) { adns__tcp_broken(ads, "write", strerror(errno)); return; } wr = 0; } } if( wr < 2 ) { r = adns__vbuf_append( &ads->tcpsend, length, 2 - wr ); assert( r ); wr = 0; } else { wr -= 2; } if ( wr < qu->query_dglen ) { r = adns__vbuf_append( &ads->tcpsend, qu->query_dgram + wr, qu->query_dglen - wr ); assert( r ); } }