//databuffer format //type.mvalue.data.type.mvalue.data... int // write_back_to_client(uchar * td, enum rrtype otype, uint8_t level, ushort id, int dlen, write_back_to_client(mbuf_type *mbuf, uchar * fr, int vlen) { struct setheader sh = { 0 }; //data in dns header int main_val = 0, dnslen = 0; uchar *msg = mbuf->buf, type; //if bigger, use TCP uchar *from = fr, *to = msg; struct mvalue *mv = NULL; int jump = 0; uint16_t temp = 0; struct hlpc hlp[100]; //p domians to compression hlp[0].name = mbuf->td; hlp[0].off = sizeof(dnsheader); hlp[0].level = mbuf->lowerdomain.label_count; hlp[0].ref = -1; hlp[0].mt = 0; hlp[0].len = mbuf->dlen; if (mbuf->dlen == 2) // root jump = sizeof(dnsheader) + 1 + sizeof(qdns); else jump = sizeof(dnsheader) + mbuf->dlen + sizeof(qdns); to = to + jump; while (vlen > 1) //vlen include type.mvalue.data. { type = from[0]; mv = (struct mvalue *)(from + 1); to = fill_rrset_in_msg(hlp, from, to, &main_val, msg); if (to == NULL) return -1; // *to = 0; vlen = vlen - 1 - mv->len - sizeof(struct mvalue); sh.an += mv->num; from = from + mv->len + 1 + sizeof(struct mvalue); // type.mv.len. /** * if previous record is CNAME(query type can't be ANY, that we don't support now), * next A & AAAA & CNAME use previous domain name (cname name). * We duplicate here to make it possible to refer previous one. */ if (type == CNAME && vlen > 1 /*&& mbuf->qtype != ANY*/ && (from[0] == A || from[0] == AAAA || from[0] == CNAME)) { main_val++; hlp[main_val].name = hlp[main_val - 1].name; hlp[main_val].off = hlp[main_val - 1].off; hlp[main_val].level = hlp[main_val - 1].level; hlp[main_val].len = hlp[main_val - 1].len; hlp[main_val].ref = -1; hlp[main_val].mt = 0; } } sh.itor = msg; sh.dlen = (mbuf->dlen == 2) ? 1: (mbuf->dlen); sh.od = mbuf->td; sh.id = mbuf->id; sh.type = mbuf->qtype; fill_header_in_msg(&sh); dnslen = to - msg; mbuf->buflen = dnslen; mbuf->addr = &(mbuf->caddr); if (mbuf->socktype == UDP) { if (dnslen > MAX_UDP_SIZE) send_tc_to_client(mbuf); else udp_write_info(mbuf, 0); //ignore send error } else { temp = DNS_GET16(dnslen); memcpy(msg - 2, &temp, sizeof(uint16_t)); mbuf->buflen = dnslen + 2; mbuf->buf = msg - 2; tcp_write_info(mbuf, 0); } //////////////////////////////////////////////////////////// //key, val, vallen, ttl offset //if now + TTL_UPDATE > ttl //return /* ret = transfer_record_to_msg(msgto, td, msg + 2, dnslen, ttloff); */ /* if (ret < 0) */ /* return -1; */ return 0; }
//return 0,continue //return idx > 0,delete and release qoutinfo //return < 0,error,nothing //0 is a valid idx,but it has a special meaning. //so we return idx + 1. and use it minus 1 int passer_auth_data(struct author *author, uchar * buf, struct sockinfo *si) { int idx, ret, pret; mbuf_type *mbuf = NULL; ushort xtype = 0; dnsheader *hdr = (dnsheader *) buf; packet_type lowerdomain; //msg buffer ret = check_enter(author, buf, &idx, &mbuf, &lowerdomain); mbuf_free(si->mbuf); si->mbuf = mbuf; //we get tc and do NOT update id //because some bad servers always return tc //thus we has chance to get another answers //then close tcp immediately, and send nothing if (ret == -2) //tc,use tcp. return -idx - 1; if (ret == 0) //late msg,server refused,continue return 0; if (ret == -1) //error msg, delete qoutinfo return idx + 1; mbuf->mxtry--; if (ret == -3) //format error, server refused, error... { mbuf->qtimes++; return 0; } si->lowerdomain = &lowerdomain; pret = passer_related_data(si, mbuf, author); if (pret < 0) return 0; //error msg,continue mbuf->fd = author->s->ludp; mbuf->addr = &(mbuf->caddr); if (pret == CNAME && mbuf->qtype == CNAME) { if (mbuf->fd != -1) { *(ushort *) buf = mbuf->cid; mbuf->buf = buf; mbuf->buflen = si->buflen; if (si->buflen > MAX_UDP_SIZE) send_tc_to_client(mbuf); else { udp_write_info(mbuf, 0); //cname.. write_log(author->loginfo, author->idx, mbuf->td, mbuf->dlen, mbuf->qtype, mbuf->addr); } } return idx + 1; } if (pret == CNAME || mbuf->qname != Q_DOMAIN) { mbuf->stat = PROCESS_QUERY; mbuf->socktype = UDP; //if prev we use tcp, use udp again return 0; } if ((pret == SOA) || (ntohs(hdr->ancount) > 0)) { if (mbuf->fd != -1) { if (mbuf->hascname == 0) { *(ushort *) buf = mbuf->cid; //no need to htons mbuf->buf = buf; mbuf->buflen = si->buflen; if (si->buflen > MAX_UDP_SIZE) send_tc_to_client(mbuf); else { udp_write_info(mbuf, 0); write_log(author->loginfo, author->idx, mbuf->td, mbuf->dlen, mbuf->qtype, mbuf->addr); } } else //has a cname,put the origin domain first { if (pret == SOA) { xtype = CNAME; } else xtype = mbuf->qtype; ret = find_record_from_mem(mbuf->td, mbuf->dlen, xtype, author->s->datasets, author->tmpbuffer, author->databuffer, &(mbuf->lowerdomain.hash[0])); if (ret > 0) { author->response++; if (mbuf->fd != -1) { mbuf->buf = mbuf->data + 2; write_back_to_client(mbuf, author->databuffer, ret); } write_log(author->loginfo, author->idx, mbuf->td, mbuf->dlen, mbuf->qtype, mbuf->addr); } } } //else printf("update record\n"); return idx + 1; } mbuf->stat = PROCESS_QUERY; //no need to find_addr in launch_new_qu mbuf->socktype = UDP; return 0; }
//databuffer format //type.mvalue.data.type.mvalue.data... int // write_back_to_client(uchar * td, enum rrtype otype, uint8_t level, ushort id, int dlen, write_back_to_client(mbuf_type *mbuf, uchar * fr, int vlen) { struct setheader sh = { 0 }; //data in dns header int main_val = 0, dnslen = 0; uchar *msg = mbuf->buf, type; //if bigger, use TCP uchar *from = fr, *to = msg; struct mvalue *mv = NULL; int jump = 0; uint16_t temp = 0; struct hlpc hlp[100]; //p domians to compression hlp[0].name = mbuf->td; hlp[0].off = sizeof(dnsheader); hlp[0].level = mbuf->lowerdomain.label_count; hlp[0].ref = -1; hlp[0].mt = 0; hlp[0].len = mbuf->dlen; jump = sizeof(dnsheader) + mbuf->dlen + sizeof(qdns); to = to + jump; while (vlen > 1) //vlen include type.mvalue.data. { type = from[0]; mv = (struct mvalue *)(from + 1); to = fill_rrset_in_msg(hlp, from, to, main_val, msg); if (to == NULL) return -1; // *to = 0; vlen = vlen - 1 - mv->len - sizeof(struct mvalue); sh.an += mv->num; if (type == CNAME) //cname must be 1 main_val++; //no all rdata is the cname's from = from + mv->len + 1 + sizeof(struct mvalue); // type.mv.len. } sh.itor = msg; sh.dlen = mbuf->dlen; sh.od = mbuf->td; sh.id = mbuf->id; sh.type = mbuf->qtype; fill_header_in_msg(&sh); dnslen = to - msg; mbuf->buflen = dnslen; mbuf->addr = &(mbuf->caddr); if (mbuf->socktype == UDP) { if (dnslen > MAX_UDP_SIZE) send_tc_to_client(mbuf); else udp_write_info(mbuf, 0); //ignore send error } else { temp = DNS_GET16(dnslen); memcpy(msg - 2, &temp, sizeof(uint16_t)); mbuf->buflen = dnslen + 2; mbuf->buf = msg - 2; tcp_write_info(mbuf, 0); } //////////////////////////////////////////////////////////// //key, val, vallen, ttl offset //if now + TTL_UPDATE > ttl //return /* ret = transfer_record_to_msg(msgto, td, msg + 2, dnslen, ttloff); */ /* if (ret < 0) */ /* return -1; */ return 0; }