8-1. DNS(Domain Name System)

 1) 도메인 이름이란?
 TCP/IP를 기반으로 인터넷상의 호스트를 구분 짓기 위해서 4byte로 표현되는 IP 주소가 사용된다. 그러나 이러한 숫자들은 사람들이 기억하기 어렵다. 그래서 나온것이 DNS이다.

 2) DNS 서버
 IP 주소가 아닌 도메인 이름을 통해서 임의의 호스트에 접근하고자 하는 경우 해당 호스트로 바로 접근을 시도하는 것이 아니다. 일단 도메인 이름을 IP 주소로 변환하는 과정을 거쳐야 한다. TCP/IP 프로토로은 IP 주소를 기준으로 호스트를 찾기 때문에 이는 당연한 과정이다. 이렇게 도메인 이름을 IP 주소로 변환하는 작업을 담당하는 서버를 DNS 서버라 한다.

 기본적으로 각각의 시스템에는 디폴트 DNS 서버가 설정되어 있다. 따라서 인터넷 브라우저를 통해서 도메인 이름을 입력하게 되면 바로 그 디폴트 서버에게 질의를 던진다. 즉, 도메인 이름에 해당하는 IP 주소를 질의하는 것이다.

 이러한 경우, 디폴트 DNS 서버가 해당 정보를 가지고 있을 경우에는 바로 응답을 해 것이고, 그렇지 못한 경우에는 다른 DNS 서버에게 물어 보게 된다.

 자세하게 설명하면, 디폴트 DNS 서버가 자신이 알고 있다면 바로 응답을 주지만 만약 그렇지 못한 경우에는 보다 상위 계층에 있는 DNS 서버에게 물어 보게 된다. 이러한 식으로 계속 물어다가 보면 결국에는 최상위 DNS 서버에게까지 올라가게 된다. 이를 ROOT DNS 서버라 한다.

 ROOT DNS서버는 질문이 들어온 내용을 어느 서버에게 물어봐야 할지 알고 있다. 따라서 자신보다 하위에 있는 DNS 서버에게 다시 질의를 던져서 결국은 IP 주소를 얻어내고, 그 결과는 질의가 진행돼 왔던 반대 방향으로 응답되어서 질의를 시작했던 호스트에게 IP 주소가 전달된다.


    8-2. IP 주소와 도메인 이름 사이의 변환

 1) 도메인 이름을 이용해서 IP 주소 얻어내기
 다음은 도메인 이름을 사용해서 IP 주소를 얻어낼 수 있는 함수이다.

gethostbyname (성공 시 hostent 구조체의 포인터, 실패 NULL 포인터 리턴) (Language : c)
  1. #include <netdb.h>
  2.  
  3. struct hostent* gethostbyname(const char * name);
 * name : 변환하고자 하는 도메인 이름을 전달한다.

 변환하고자 하는 도메인 이름을 인자로 전달하면 IP 주소가 리턴된다. 단 IP 주소가 바로 리턴되는 것이 아니라, hostent라는 구조체 변수를 통해서 리턴하게 된다. hostent 구조체는 다음과 같다.

(Language : c)
  1. struct hostent{
  2.     char *h_name;         /* official name */
  3.     char **h_aliases;     /* alias name */
  4.     int h_addrtype;        /* host address type */
  5.     int h_length;            /* length of address */
  6.     char **h_addr_list;   /* list of addresses */
  7. }
 * h_name : 공식 도메인 이름이 저장된다.
 * h_aliases : 공식 도메인 이름 외에 alias(별명) name 정보들이 저장된다.
 * h_addrtype : gethostbyname 함수는 IPv4뿐 아니라 IPv6까지 지원을 한다. 그렇기 때문에 h_addr_list로 전달된 IP 주소 체계가 무엇인지를 가르쳐 준다.
 * h_length : 결과로 전달되는 IP 주소의 길이를 가르쳐 준다. IPv4인 경우는 주소의 길이가 4바이트이므로 4가 전달될 것이고, IPv6인 경우는 16바이느가 되므로 16이 저장될 것이다.
 * h_addr_list : gethostbyname 함수로 전달된 도메인 이름에 해당하는 IP 주소를 전달해 준다. 그런데 큰 회사 같은 경우는 여러 대의 서버를 운영하기 때문에 하나의 도메인 이름에 대응하는 IP 주소가 여러 개가 될 수 있다.

 다음은 gethostbyname을 사용한 코드이다.

gethostbyname.c (Language : c)
  1. /***************************************************************************
  2. *            gethostbyname.c
  3. *
  4. *  Sat Jan  5 19:11:43 2008
  5. *  Copyright  2008  pchero21
  6. *  pchero21@gmail.com
  7. ****************************************************************************/
  8.  
  9. /*
  10. *  This program is free software; you can redistribute it and/or modify
  11. *  it under the terms of the GNU General Public License as published by
  12. *  the Free Software Foundation; either version 2 of the License, or
  13. *  (at your option) any later version.
  14. *
  15. *  This program is distributed in the hope that it will be useful,
  16. *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. *  GNU General Public License for more details.
  19. *
  20. *  You should have received a copy of the GNU General Public License
  21. *  along with this program; if not, write to the Free Software
  22. *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. */
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <unistd.h>
  28. #include <arpa/inet.h>
  29. #include <netdb.h>
  30.  
  31. void error_handling(char *message);
  32.  
  33. int main(int argc, char **argv)
  34. {
  35.     int i;
  36.     struct hostent *host;
  37.        
  38.     if(argc != 2) {
  39.         printf("Usage : %s <addr> \n", argv[0]);
  40.         exit(1);
  41.     }
  42.    
  43.     host = gethostbyname(argv[1]);
  44.     if(!host)
  45.         error_handling("gethostbyname() error!");
  46.    
  47.     printf("Officially name : %s \n\n", host->h_name);
  48.    
  49.     puts("Aliases-------------------------");
  50.     for(i = 0; host->h_aliases[i]; i++) {
  51.         puts(host->h_aliases[i]);
  52.     }
  53.    
  54.     printf("Address Type : %s \n", host->h_addrtype == AF_INET ? "AF_INET" : "AF_INET6");
  55.  
  56.     puts("IP Address--------------------");
  57.     for(i = 0; host->h_addr_list[i]; i++) {
  58.         puts(inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
  59.     }
  60.        
  61.     return 0;
  62. }
  63.  
  64. void error_handling(char *message)
  65. {
  66.     fputs(message, stderr);
  67.     fputc('\n', stderr);
  68.     exit(1);
  69. }
  70.  

사용자 삽입 이미지

 한가지 주의해야 할 사항이 있다. 58번째 라인에 있는 다음 코드를 보면...
puts(inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
  h_addr_list가 가리키는 것은 문자열 포인터이다. 그런데 참조를 할 때는 in_addr 구조체의 포인터로 변환을 하고 나서 참조를 한다. 이 말은 h_addr_list가 가리키는 배열은 문자열을 가리킬 수 있는 char 포인터 배열이지만, 이 배열이 저장하고 있는 포인터가 실제로는 in_addr 구조테 변수를 가리키고 있다는 뜻이 된다.

 따라서, 참조하기 전에 반드시 형 변환을 해야만 한다. 이렇게 하는 이유는 hostent 구조체는 IPv4 만을 위한 것이 아니라, IPv6 기반의 주소 정보를 나타내는 데에도 사용되기 때문이다. 그래서 일반화하기 위해서 char*로 선언한 것이다.

 2) IP 주소를 이용해서 도메인 이름 알아내기
 다음은 gethostbyname과 상대적인 기능을 하는 함수이다. 즉 IP 주소를 사용해서 도메인 이름을 얻을 때 사용할 수 있는 함수이다.

gethostbyaddr (성공 시 hostent 구조체의 포인터, 실패 시 NULL 포인터 리턴) (Language : c)
  1. #include <netdb.h>
  2.  
  3. struct hostent* gethostbyaddr(const char *addr, int len, int type);
 * addr : 선언은 char*로 되어 있지만 실제로 요구하는 것은 변경할 IP 주소 정보를 지니고 있는 in_addr 구조체 변수 포인터이다. 물론 IPv4와 IPv6 두 주소 체계를 모두 수용하기 위해서 선택한 일반화에 해당한다.
 * len : 입력되는 주소의 길이를 전달한다. IPv4인 경우 4, IPv6인 경우 16을 전달한다.
 * type : 입력되는 주소의 주소 체계(타입)를 전달한다. AF_INET 혹은 AF_INET6가 될 것이다.

 다음은 gethostbyaddr 함수를 이용한 코드이다.

gethostbyaddr.c (Language : c)
  1. /***************************************************************************
  2. *            gethostbyaddr.c
  3. *
  4. *  Sat Jan  5 22:18:59 2008
  5. *  Copyright  2008  pchero21
  6. *  pchero21@gmail.com
  7. ****************************************************************************/
  8.  
  9. /*
  10. *  This program is free software; you can redistribute it and/or modify
  11. *  it under the terms of the GNU General Public License as published by
  12. *  the Free Software Foundation; either version 2 of the License, or
  13. *  (at your option) any later version.
  14. *
  15. *  This program is distributed in the hope that it will be useful,
  16. *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. *  GNU General Public License for more details.
  19. *
  20. *  You should have received a copy of the GNU General Public License
  21. *  along with this program; if not, write to the Free Software
  22. *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. */
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <unistd.h>
  29. #include <arpa/inet.h>
  30. #include <netdb.h>
  31.  
  32.  
  33. void error_handling(char *message);
  34.  
  35. int main(int argc, char **argv)
  36. {
  37.     struct hostent *host;
  38.     struct sockaddr_in addr;
  39.     int i;
  40.    
  41.     if(argc != 2) {
  42.         printf("Usage : %s <IP> \n", argv[0]);
  43.         exit(1);
  44.     }
  45.    
  46.     memset(&addr, 0, sizeof(addr));
  47.     addr.sin_addr.s_addr = inet_addr(argv[1]);
  48.  
  49.     host = gethostbyaddr((char*)&(addr.sin_addr.s_addr), 4, AF_INET);
  50.     if(!host)
  51.         error_handling("gethostbyaddr() error!");
  52.    
  53.     printf("Officially name : %s \n\n", host->h_name);
  54.    
  55.     puts("Aliases----------------------");
  56.     for(i = 0; host->h_aliases[i]; i++) {
  57.         puts(host->h_aliases[i]);
  58.     }
  59.    
  60.     printf("Address Type : %s \n", host->h_addrtype == AF_INET ? "AF_INET" : "AF_INET6");
  61.  
  62.     puts("IP Address------------------");
  63.     for(i = 0; host->h_addr_list[i]; i++) {
  64.         puts(inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
  65.     }
  66.     return 0;
  67. }
  68.  
  69. void error_handling(char *message)
  70. {
  71.     fputs(message, stderr);
  72.     fputc('\n', stderr);
  73.     exit(1);
  74. }
  75.  

 실행 화면

사용자 삽입 이미지

 아마도 자신의 컴퓨터에서 IP를 입력하여도 결과값이 제대로 나오지 않는 경우가 있을것이다.

 그럴 경우 다음의 링크를 참조 바란다.

 관련 링크 : http://pchero21.com/133