Shammer's Philosophy

My private adversaria

getnameinfo-sample_beta

getnameinfo-sample_alpha - Shammerismの内容から、getnameinfo を使用する際にはIPアドレスをベースに動作させたい、と思い考えてみた。getnameinfo に必要な入力は sockaddr 構造体。IPアドレスから sockaddr 構造体を手に入れるには・・・ということで、Shammerismで使ったgetaddrinfoを使おうと思い立った。
addrinfo 構造体の内容を再引用。

     struct addrinfo {
             int ai_flags;           /* input flags */
             int ai_family;          /* protocol family for socket */
             int ai_socktype;        /* socket type */
             int ai_protocol;        /* protocol for socket */
             socklen_t ai_addrlen;   /* length of socket-address */
             struct sockaddr *ai_addr; /* socket-address for socket */
             char *ai_canonname;     /* canonical name for service location */
             struct addrinfo *ai_next; /* pointer to next in list */
     };

ai_addr が目的のsockaddr構造体だ。というわけで、

  1. IPアドレスからaddrinfo構造体を作成
  2. ホスト名やサービス名を格納するための変数を用意
  3. 作成したaddrinfo->ai_addrをgetnameinfoの引数に渡す
  4. 同時にホスト名やサービス名を格納するための変数も渡す

という感じでいけるはず。

#include <arpa/inet.h>
#include <err.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char* args[]){
    if( argc == 3 ){
	// man getnameinfo sample
	// struct sockaddr *sa;    /* input */
	// char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
	//
	// if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
	//     errx(1, "could not get numeric hostname");
	// }
	// printf("host=%s, serv=%s\n", hbuf, sbuf);
	struct addrinfo hints, *res, *res0;
	int error;
	char addrstring[100];
	void *ptr;
	char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;

	error = getaddrinfo(args[1], NULL, &hints, &res0);
	if( error ) {
	    errx(1, "%s\n", gai_strerror(error));
	}
	for( res = res0 ; res != NULL ; res = res->ai_next) {
	    getnameinfo((struct sockaddr *)res->ai_addr,
			res->ai_addrlen,
			hbuf,
			sizeof(hbuf),
			sbuf,
			sizeof(sbuf),
			NI_NUMERICHOST | NI_NUMERICSERV);
	    printf("host=%s, serv=%s\n", hbuf, sbuf);
	}
	if( res != NULL ){
	    freeaddrinfo(res);
	}
    }
    else {
	printf("Usage: %s $IP_ADDRESS $PORT\n", args[0]);
    }
    return 0;
}

実行結果は以下。

$ ./a.out 127.0.0.1 21
host=127.0.0.1, serv=0
$ ./a.out 127.0.0.1 22
host=127.0.0.1, serv=0
$ ./a.out 127.0.0.1 23
host=127.0.0.1, serv=0
$ ./a.out 127.0.0.1 80
host=127.0.0.1, serv=0

サービスは相変わらず0だ・・・うーむ、、、