|
|
- Welcome to
Hiroshi's Home Page - |
|
|
|
||
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)
|
|
||
|
(c) Copyright 1998-2002 Hiroshi OHNO All
right reserved. |
||