@ひろP

    - Welcome to Hiroshi's Home Page -
    趣味を中心とした個人のホームページです


@ひろP / ホビー / プロフィール / ブックマーク / 掲示板 / アルバム / サイトマップ / memo

MXを引くプログラム - その2 - 結果の出力 …

 

res_search()関数で取得した検索結果を利用するには、データを解析し、MXのホスト名を抜き出す必要がある。

データは、ネットワークバイトオーダー(ビッグエンディアン)なので注意が必要である。

受信したデータの中で、ホスト名やドメイン名は圧縮されている部分がある。これは重複するドメイン名などを、複数保持するのではなく、オフセット値で持つことで実現されている。

これらの名前を展開するには、dn_expand()関数を用いる。

int dn_expand(unsigned char *msg, unsigned char *eomorig, unsigned char *comp_dn, unsigned char *exp_dn, int length);

msg 受信したデータの先頭を示すポインタ
eomorig 受信したデータの次を示すポインタ(データの最後+1)
comp_dn 圧縮されたデータの先頭を示すポインタ
exp_dn 展開するバッファ
length バッファサイズ
戻り値は、展開するのに要したデータ数

answerで受信するデータは、RFC1035(4.MESSAGES)で記述されているフォーマットそのもので、データのヘッダ部分は、arpa/nameser_compat.h内でHEADER構造体として定義されている。(RedHat Linux 7.3の開発環境)

受信したデータからMXレコードのPREFERENCE値とEXCHANGE値を出力するサンプルを以下に示す。

#include <stdio.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>

int main(int argc, char *argv[])
{
        int i, rc;
        unsigned char ans[PACKETSZ];
        HEADER *hdr = (HEADER *)ans;
        int anslen;

        for(i = 1; i < argc; i++) {
                int j;
                unsigned char *p;
                unsigned short qdcount;
                unsigned short ancount;

                anslen = res_query(argv[i], C_IN, T_MX, ans, sizeof(ans));
                printf("res_query(): %d\n", anslen);
                if(anslen < sizeof(HEADER))
                        continue;
                /* Response code == 0: No error condition */
                if(hdr->rcode != 0)
                        continue;

                /* qdcount: the number of entries in the question
                        section. */
                qdcount = ntohs(hdr->qdcount);
                p = ans + sizeof(HEADER);
                /* skip question section */
                for(j = 0; j < qdcount; j++) {
                        unsigned char tmpname[NS_MAXDNAME];
                        rc = dn_expand(ans, ans + anslen,
                                p, tmpname, sizeof(tmpname));
                        printf("dn_expand(): %d %s\n", rc, tmpname);
                        /* add length of qname + qtype + qclass */
                        p += rc + NS_INT16SZ + NS_INT16SZ;
                }

                /* ancount: the number of resource records in
                        the answer section. */
                ancount = ntohs(hdr->ancount);
                /* get answer section (resource record) */
                for(j = 0; j < ancount; j++) {
                        unsigned char tmpname[NS_MAXDNAME];
                        unsigned short tmptype;
                        unsigned short tmpclass;
                        unsigned long tmpttl;
                        unsigned short tmprdlen;
                        unsigned short tmppreference;
                        unsigned char tmpexchange[NS_MAXDNAME];

                        rc = dn_expand(ans, ans + anslen,
                                p, tmpname, sizeof(tmpname));
                        printf("dn_expand(): %d %s\n", rc, tmpname);
                        /* add length of name */
                        p += rc;
                        /* get type */
                        GETSHORT(tmptype, p);
                        /* get class */
                        GETSHORT(tmpclass, p);
                        /* get ttl */
                        GETLONG(tmpclass, p);
                        /* get rdlength */
                        GETSHORT(tmprdlen, p);

                        /* get MX RDATA format */
                        if(tmptype != T_MX) {
                                p += tmprdlen;
                                continue;
                        }
                        /* get preference */
                        GETSHORT(tmppreference, p);
                        /* get exchange */
                        rc = dn_expand(ans, ans + anslen,
                                p, tmpexchange, sizeof(tmpexchange));
                        printf("exchange: %d %s\n", tmppreference, tmpexchange);
                        p += rc;
                }
        }

        return 0;
}

GETSHORT()マクロは、ネットワークバイトオーダーの16ビットデータを取得し、ポインタを2つ進める、GETLONG()マクロは、32ビット版である。

<<前へ

(2002/06/03)

@ひろP / ホビー / プロフィール / ブックマーク / 掲示板 / アルバム / サイトマップ / memo

@ひろP

(c) Copyright 1998-2002 Hiroshi OHNO All right reserved.
E-MAIL: hirop0730@hotmail.com / hiroshi@bigfield.com