Example #1
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;
}
Example #2
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;
}
Example #3
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;
}