Shammer's Philosophy

My private adversaria

nslookup sample C version - 関数版

nslookup sample C version - Shammerismでは、全て main の中に書いていたが、IP アドレスを取得する処理を関数に分けてみた。自分が作成する予定の HTTP Client では、IPv4 のみ使用するつもりなので IPv6 のところは一旦コメントアウト。それなら inet_ntoa でもいいじゃないか、というのもあるけれども、いつ IPv6 に切り替えるかわからないのでそのためのコードも残しておくことにした。

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

char * get_ip_addr(char * hostname){
    char temp[17] = {'0'};
    struct addrinfo hints, *res, *res0;
    int error;
    void * ptr;

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

    error = getaddrinfo(hostname, NULL, &hints, &res0);
    if( error ) {
	errx(1, "%s", gai_strerror(error));
    }

    int i = 0;
    for( res = res0 ; res ; res = res->ai_next ) {
	switch(res->ai_family) {
	case AF_INET:
	    ptr = &(((struct sockaddr_in *)res->ai_addr)->sin_addr);
	    inet_ntop(res->ai_family, ptr, temp, sizeof(temp));
	    break;
	case AF_INET6:
	    // Don't use IPv6 address.
	    // ptr = &(((struct sockaddr_in6 *)res->ai_addr)->sin6_addr);
	    // inet_ntop(res->ai_family, ptr, temp, sizeof(temp));
	    continue;
	}
	i++;
    }
    freeaddrinfo(res0);

    char * ip = (char *)malloc(strlen(temp) + 1);
    strcpy(ip, temp);
    
    return ip;
}

int main(int argc, char *args[]){
    if( argc == 2 ){
	char * ip = get_ip_addr(args[1]);
	printf("The IP address of \"%s\" is %s.\n", args[1], ip);
	free(ip);
    }
    else {
	printf("Usage: %s $HOST_NAME(not IP address)\n", args[0]);
    }
    return 0;
}

内部のDNSに登録されたホストで確認したから実行例は書かないけれど、コンパイルも動作も問題なし。