//we'd better send the right domain and id int send_tc_to_client(mbuf_type *mbuf) { uchar *itor = mbuf->buf; dnsheader *hdr = (dnsheader *) itor; qdns *qd = NULL; if (mbuf->td == NULL) return -1; hdr->id = mbuf->id; hdr->flags = 0; hdr->flags = SET_QR_R(hdr->flags); hdr->flags = SET_RA(hdr->flags); hdr->flags = SET_TC(hdr->flags); hdr->flags = htons(hdr->flags); hdr->qdcount = htons(1); hdr->ancount = hdr->nscount = hdr->arcount = htons(0); itor += sizeof(dnsheader); memcpy(itor, mbuf->td, mbuf->dlen); itor = itor + mbuf->dlen; qd = (qdns *) itor; qd->type = htons(mbuf->qtype); qd->dclass = htons(CLASS_IN); itor += sizeof(qdns); mbuf->buflen = itor - mbuf->buf; udp_write_info(mbuf, 0); return 0; }
//we'd better send the right domain and id int send_tc_to_client(uchar *td,struct sockinfo *si,ushort cid) { uchar buffer[255] = {0},*itor = buffer; dnsheader *hdr = (dnsheader*)itor; qdns *qd = NULL; int dlen = -1; if(td == NULL || si == NULL) return -1; hdr->id = cid; hdr->flags = 0; hdr->flags = SET_QR_R(hdr->flags); hdr->flags = SET_RA(hdr->flags); hdr->flags = SET_TC(hdr->flags); hdr->flags = htons(hdr->flags); hdr->qdcount = htons(1); hdr->ancount = hdr->nscount = hdr->arcount = htons(0); itor += sizeof(dnsheader); dlen = strlen(td + 1); memcpy(itor,td + 1,dlen + 1); itor = itor + dlen + 1; qd = (qdns*)itor; qd->type = htons(td[0]); qd->dclass = htons(CLASS_IN); itor += sizeof(qdns); si->buf = buffer; si->buflen = itor - buffer; udp_write_info(si,0); return 0; }
int query_from_auth_server(mbuf_type *mbuf, struct author *author) { ushort id = mbuf->aid, type; uchar *buffer = mbuf->tempbuffer; uchar *ip = author->ip; int len, i, st = 1, ret; struct mvalue *mv = NULL; // struct sockinfo si; //dbg_print_td(qo->td); if (mbuf->qname == Q_NS) type = A; else type = mbuf->qtype; mbuf->mxtry++; if (mbuf->socktype == UDP) { len = make_dns_msg_for_new(buffer, id, mbuf->qing, mbuf->qlen, type); mbuf->buf = buffer; mbuf->buflen = len; mbuf->fd = author->audp; mv = (struct mvalue *) ip; while (mv->num > 0) { ip += sizeof(struct mvalue); for (i = 0; i < mv->num; i++) { make_addr_from_bin(&(mbuf->aaddr), ip + i * 4); //ipv4 only //dbg_print_addr((struct sockaddr_in*)&(si.addr)); mbuf->aaddr.sin_port = htons(53); mbuf->addr = &(mbuf->aaddr); ret = udp_write_info(mbuf, 0); if (ret > 0) //success st++; if (st > mbuf->mxtry) return 0; } ip += mv->len; mv = (struct mvalue *) ip; if (st > MOST_TRY_PER_QUERY) break; } } 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; 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; }
//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; }