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

📄 ch13.check_soa.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************** * check_soa -- Retrieve the SOA record from each name server   * *     for a given domain and print out the serial number.      * *                                                              * * usage: check_soa domain                                      * *                                                              * * The following errors are reported:                           * *     o There is no address for a server.                      * *     o There is no server running on this host.               * *     o There was no response from a server.                   * *     o The server is not authoritative for the domain.        * *     o The response had an error response code.               * *     o The response had more than one answer.                 * *     o The response answer did not contain an SOA record.     * *     o The expansion of a compressed domain name failed.      * ****************************************************************//* Various header files */#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <arpa/inet.h>#include <arpa/nameser.h>#include <resolv.h>#include <string.h>/* Error variables */extern int h_errno;  /* for resolver errors */extern int errno;    /* general system errors *//* Our own routines; code included later in this chapter */void nsError();            /* report resolver errors */void findNameServers();    /* find a domain's name servers */void queryNameServers();   /* grab SOA records from servers */void returnCodeError();    /* report response packet errors */int  skipToData();         /* skip to the resource record data */int  skipName();           /* skip a compressed name *//* Maximum number of name servers we will check */#define NSLIMIT 20main(argc, argv)int argc;char *argv[];{    char *nsList[NSLIMIT]; /* list of name servers */    int  nsNum = 0;        /* number of name servers in list */    /* sanity check: one (and only one) argument? */    if(argc != 2){        (void) fprintf(stderr, "usage: %s domain\n", argv[0]);        exit(1);    }    (void) res_init();    /*      * Find the name servers for the domain.     * The name servers are written into nsList.     */    findNameServers(argv[1], nsList, &nsNum);    /*      * Query each name server for the domain's SOA record.     * The name servers are read from nsList.     */    queryNameServers(argv[1], nsList, nsNum);    exit(0);}/**************************************************************** * findNameServers -- find all of the name servers for the      * *     given domain and store their names in nsList.  nsNum is  * *     the number of servers in the nsList array.               * ****************************************************************/voidfindNameServers(domain, nsList, nsNum)char *domain;char *nsList[];int  *nsNum;{    union {        HEADER hdr;           /* defined in resolv.h */        u_char buf[PACKETSZ]; /* defined in arpa/nameser.h */    } response;               /* response buffers */    int responseLen;          /* buffer length */    u_char  *cp;       /* character pointer to parse DNS packet */    u_char  *endOfMsg; /* need to know the end of the message */    u_short class;     /* classes defined in arpa/nameser.h */    u_short type;      /* types defined in arpa/nameser.h */    u_long  ttl;       /* resource record time to live */    u_short dlen;      /* size of resource record data */    int i, count, dup; /* misc variables */    /*      * Look up the NS records for the given domain name.     * We expect the domain to be a fully qualified name, so     * we use res_query().  If we wanted the resolver search      * algorithm, we would have used res_search() instead.     */    if((responseLen =            res_query(domain,      /* the domain we care about   */                     C_IN,        /* Internet class records     */                     T_NS,        /* Look up name server records*/                     (u_char *)&response,      /*response buffer*/                     sizeof(response)))        /*buffer size    */                                        < 0){  /*If negative    */        nsError(h_errno, domain); /* report the error           */        exit(1);                  /* and quit                   */    }    /*     * Keep track of the end of the message so we don't      * pass it while parsing the response.  responseLen is      * the value returned by res_query.     */    endOfMsg = response.buf + responseLen;    /*     * Set a pointer to the start of the question section,      * which begins immediately AFTER the header.     */    cp = response.buf + sizeof(HEADER);    /*     * Skip over the whole question section.  The question      * section is comprised of a name, a type, and a class.       * QFIXEDSZ (defined in arpa/nameser.h) is the size of      * the type and class portions, which is fixed.  Therefore,      * we can skip the question section by skipping the      * name (at the beginning) and then advancing QFIXEDSZ.     * After this calculation, cp points to the start of the      * answer section, which is a list of NS records.     */    cp += skipName(cp, endOfMsg) + QFIXEDSZ;    /*     * Create a list of name servers from the response.     * NS records may be in the answer section and/or in the     * authority section depending on the DNS implementation.       * Walk through both.  The name server addresses may be in     * the additional records section, but we will ignore them     * since it is much easier to call gethostbyname() later     * than to parse and store the addresses here.     */    count = ntohs(response.hdr.ancount) +             ntohs(response.hdr.nscount);    while (    (--count >= 0)        /* still more records     */            && (cp < endOfMsg)       /* still inside the packet*/            && (*nsNum < NSLIMIT)) { /* still under our limit  */        /* Skip to the data portion of the resource record */        cp += skipToData(cp, &type, &class, &ttl, &dlen, endOfMsg);        if (type == T_NS) {            /*             * Allocate storage for the name.  Like any good              * programmer should, we test malloc's return value,              * and quit if it fails.             */            nsList[*nsNum] = (char *) malloc (MAXDNAME);            if(nsList[*nsNum] == NULL){                (void) fprintf(stderr, "malloc failed\n");                exit(1);            }            /* Expand the name server's name */            if (dn_expand(response.buf, /* Start of the packet   */                          endOfMsg,     /* End of the packet     */                          cp,           /* Position in the packet*/                          (u_char *)nsList[*nsNum], /* Result    */                          MAXDNAME)     /* size of nsList buffer */                                    < 0) { /* Negative: error    */                (void) fprintf(stderr, "dn_expand failed\n");                exit(1);            }            /*             * Check the name we've just unpacked and add it to              * the list of servers if it is not a duplicate.             * If it is a duplicate, just ignore it.             */            for(i = 0, dup=0; (i < *nsNum) && !dup; i++)                dup = !strcasecmp(nsList[i], nsList[*nsNum]);            if(dup)                 free(nsList[*nsNum]);            else                (*nsNum)++;        }        /* Advance the pointer over the resource record data */        cp += dlen;    } /* end of while */}/**************************************************************** * queryNameServers -- Query each of the name servers in nsList * *     for the SOA record of the given domain.  Report any      * *     errors encountered.  (e.g., a name server not running or * *     the response not being an authoritative response.)  If   * *     there are no errors, print out the serial number for the * *     domain.                                                  * ****************************************************************/voidqueryNameServers(domain, nsList, nsNum)char *domain;char *nsList[];int nsNum;{    union {        HEADER hdr;            /* defined in resolv.h */        u_char buf[PACKETSZ];  /* defined in arpa/nameser.h */    } query, response;         /* query and response buffers */    int responseLen, queryLen; /* buffer lengths */    u_char  *cp;       /* character pointer to parse DNS packet */    u_char  *endOfMsg; /* need to know the end of the message */    u_short class;     /* classes defined in arpa/nameser.h */    u_short type;      /* types defined in arpa/nameser.h */    u_long  ttl;       /* resource record time to live */    u_short dlen;      /* size of resource record data */    struct in_addr saveNsAddr[MAXNS];  /* addrs saved from _res */    int nsCount;          /* count of addresses saved from _res */    struct hostent *host; /* structure for looking up ns addr */    int i;                /* counter variable */    /*     * Save the _res name server list since      * we will need to restore it later.     */    nsCount = _res.nscount;    for(i = 0; i < nsCount; i++)      saveNsAddr[i] = _res.nsaddr_list[i].sin_addr;    /*     * Turn off the search algorithm and turn off appending      * the default domain before we call gethostbyname(); the      * name server names will be fully qualified.     */    _res.options &= ~(RES_DNSRCH | RES_DEFNAMES);    /*     * Query each name server for an SOA record.     */    for(nsNum-- ; nsNum >= 0; nsNum--){        /*          * First, we have to get the IP address of every server.         * So far, all we have are names.  We use gethostbyname         * to get the addresses, rather than anything fancy.         * But first, we have to restore certain values in _res          * because _res affects gethostbyname().  (We altered         * _res in the previous iteration through the loop.)         *         * We can't just call res_init() again to restore         * these values since some of the _res fields are          * initialized when the variable is declared, not when          * res_init() is called.         */        _res.options |= RES_RECURSE;  /* recursion on (default) */        _res.retry = 4;               /* 4 retries (default)    */        _res.nscount = nsCount;       /* original name servers  */        for(i = 0; i < nsCount; i++)            _res.nsaddr_list[i].sin_addr = saveNsAddr[i];        /* Look up the name server's address */        host = gethostbyname(nsList[nsNum]);        if (host == NULL) {            (void) fprintf(stderr,"There is no address for %s\n",

⌨️ 快捷键说明

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