⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch13.check_soa.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
                                              nsList[nsNum]);            continue; /* nsNum for-loop */        }        /*         * Now get ready for the real fun.  host contains IP          * addresses for the name server we're testing.         * Store the first address for host in the _res          * structure.  Soon, we'll look up the SOA record...         */        (void) memcpy((void *)&_res.nsaddr_list[0].sin_addr,           (void *)host->h_addr_list[0], (size_t)host->h_length);        _res.nscount = 1;        /*         * Turn off recursion.  We don't want the name server         * querying another server for the SOA record; this name          * server ought to be authoritative for this data.         */        _res.options &= ~RES_RECURSE;        /*         * Reduce the number of retries.  We may be checking         * several name servers, so we don't want to wait too         * long for any one server.  With two retries and only         * one address to query, we'll wait at most 15 seconds.         */        _res.retry = 2;        /*         * We want to see the response code in the next         * response, so we must make the query packet and          * send it ourselves instead of having res_query()         * do it for us.  If res_query() returned -1, there         * might not be a response to look at.           *         * There is no need to check for res_mkquery()          * returning -1.  If the compression was going to          * fail, it would have failed when we called          * res_query() earlier with this domain name.         */        queryLen = res_mkquery(                     QUERY,           /* regular query         */                     domain,          /* the domain to look up */                     C_IN,            /* Internet type         */                     T_SOA,           /* Look up an SOA record */                     (char *)NULL,    /* always NULL           */                     0,               /* length of NULL        */                     (struct rrec *)NULL, /* always NULL       */                     (char *)&query,  /* buffer for the query  */                     sizeof(query));  /* size of the buffer    */        /*         * Send the query packet.  If there is no name server         * running on the target host, res_send() returns -1         * and errno is ECONNREFUSED.  First, clear out errno.         */        errno = 0;        if((responseLen = res_send((char *)&query, /* the query  */                                    queryLen,      /* true length*/                                    (char *)&response, /*buffer  */                                    sizeof(response))) /*buf size*/                                        < 0){          /* error  */            if(errno == ECONNREFUSED) { /* no server on the host */                (void) fprintf(stderr,                     "There is no name server running on %s\n",                    nsList[nsNum]);            } else {                    /* anything else: no response */                (void) fprintf(stderr,                     "There was no response from %s\n",                     nsList[nsNum]);            }            continue; /* nsNum for-loop */        }        /*         * Set up the pointers to parse the response.         * We set up two pointers: one to the end of the message          * (so we can test for overruns) and one to the question          * section (which we'll move as we parse the response).         */        endOfMsg = response.buf + responseLen;        cp = response.buf + sizeof(HEADER);                     /*         * If the response reports an error, issue a message         * and proceed to the next server in the list.         */        if(response.hdr.rcode != NOERROR){            returnCodeError((int)response.hdr.rcode,                                                   nsList[nsNum]);            continue; /* nsNum for-loop */        }        /*         * Did we receive an authoritative response?  Check the          * authoritative answer bit.  If the server isn't         * authoritative, report it, and go on to the next server.         */        if(!response.hdr.aa){            (void) fprintf(stderr,                 "%s is not authoritative for %s\n",                nsList[nsNum], domain);            continue; /* nsNum for-loop */        }        /*          * The response should only contain one answer; if more,         * report the error, and proceed to the next server.         */        if(ntohs(response.hdr.ancount) != 1){            (void) fprintf(stderr,                 "%s: expected 1 answer, got %d\n",                nsList[nsNum], ntohs(response.hdr.ancount));            continue; /* nsNum for-loop */        }        /*          * Skip the question section (we know what we asked,          * don't we?).  cp now points to the answer section.         */        cp += skipName(cp, endOfMsg) + QFIXEDSZ;        /*          * cp is now pointing at a resource record in the answer          * section.  Skip to the data portion of this record;         * in the process, extract the type, class, etc.          */        cp += skipToData(cp, &type, &class, &ttl, &dlen, endOfMsg);        /*          * We asked for an SOA record; if we got something else,         * report the error and proceed to the next server.         */        if (type != T_SOA) {            (void) fprintf(stderr,                 "%s: expected answer type %d, got %d\n",                nsList[nsNum], T_SOA, type);            continue; /* nsNum for-loop */        }        /*          * Skip the SOA origin and mail address, which we don't         * care about.  Both are standard "compressed names."         */        cp += skipName(cp, endOfMsg);        cp += skipName(cp, endOfMsg);        /* cp now points to the serial number; print it. */        (void) printf("%s has serial number %d\n",             nsList[nsNum], _getlong(cp));    } /* end of nsNum for-loop */}/**************************************************************** * skipName -- This routine skips over a domain name.  If the   * *     domain name expansion fails, it reports an error and     * *     exits.  dn_skipname() is probably not on your manual     * *     page; it is similar to dn_expand() except that it just   * *     skips over the name.  dn_skipname() is in res_comp.c if  * *     you need to find it.                                     * ****************************************************************/intskipName(cp, endOfMsg)u_char *cp;u_char *endOfMsg;{    int n;    if((n = dn_skipname(cp, endOfMsg)) < 0){        (void) fprintf(stderr, "dn_skipname failed\n");        exit(1);    }    return(n);}/**************************************************************** * skipToData -- This routine advances the cp pointer to the    * *     start of the resource record data portion.  On the way,  * *     it fills in the type, class, ttl, and data length        * ****************************************************************/intskipToData(cp, type, class, ttl, dlen, endOfMsg)u_char  *cp;u_short *type;u_short *class;u_long  *ttl;u_short *dlen;u_char  *endOfMsg;{    u_char *tmp_cp = cp;  /* temporary version of cp */    /* Skip the domain name; it matches the name we looked up */    tmp_cp += skipName(tmp_cp, endOfMsg);    /*     * Grab the type, class, and ttl.  The routines called     * _getshort() and _getlong() are also resolver routines      * you may not find in a manual page.  They are in      * res_comp.c if you want to see them.     */    *type = _getshort(tmp_cp);    tmp_cp += sizeof(u_short);    *class = _getshort(tmp_cp);    tmp_cp += sizeof(u_short);    *ttl = _getlong(tmp_cp);    tmp_cp += sizeof(u_long);    *dlen = _getshort(tmp_cp);    tmp_cp += sizeof(u_short);    return(tmp_cp - cp);}/**************************************************************** * nsError -- Print an error message from h_errno for a failure * *     looking up NS records.  res_query() converts the DNS     * *     packet return code to a smaller list of errors and       * *     places the error value in h_errno.  There is a routine   * *     called herror() for printing out strings from h_errno    * *     like perror() does for errno.  Unfortunately, the        * *     herror() messages assume you are looking up address      * *     records for hosts.  In this program, we are looking up   * *     NS records for domains, so we need our own list of error * *     strings.                                                 * ****************************************************************/voidnsError(error, domain)int error;char *domain;{    switch(error){        case HOST_NOT_FOUND:          (void) fprintf(stderr, "Unknown domain: %s\n", domain);          break;        case NO_DATA:          (void) fprintf(stderr, "No NS records for %s\n", domain);           break;        case TRY_AGAIN:          (void) fprintf(stderr, "No response for NS query\n");          break;        default:          (void) fprintf(stderr, "Unexpected error\n");          break;    }}/**************************************************************** * returnCodeError -- print out an error message from a DNS     * *     response return code.                                    * ****************************************************************/voidreturnCodeError(rcode, nameserver)int rcode;char *nameserver;{    (void) fprintf(stderr, "%s: ", nameserver);    switch(rcode){        case FORMERR:          (void) fprintf(stderr, "FORMERR response\n");          break;        case SERVFAIL:          (void) fprintf(stderr, "SERVFAIL response\n");          break;        case NXDOMAIN:          (void) fprintf(stderr, "NXDOMAIN response\n");          break;        case NOTIMP:          (void) fprintf(stderr, "NOTIMP response\n");          break;        case REFUSED:          (void) fprintf(stderr, "REFUSED response\n");          break;        default:          (void) fprintf(stderr, "unexpected return code\n");          break;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -