호스트이름과 네트워크이름 찾기 (Hostname and Network Name Lookups) System Software Lab. 홍창범 한남대학교 컴퓨터공학과 컴퓨터 네트워크 실험실
목차 왜 이름이 필요한가? 로컬 시스템에 대한 정보 얻기 호스트이름과 도메인 이름 정보 호스트이름을 IP 번호로 분석
왜 이름이 필요한가? 이름은 번호에 비하여 인간 친화적. IP 번호가 바뀌는 동안 이름은 변화지 않는다. ftp://ftp.redhat.com 216.148.218.192 Client 63.240.14.62
호스트 정보 얻기 – uname(2) uname(2) 함수 함수 원형 에러 처리 현재 시스템(호스트)에 대한 정보를 buf 포인터가 가르키는 구조체에 기록 함수 원형 에러 처리 성공 : 음수가 아닌 정수 반환 에러 : –1을 반환하고 errno를 설정 #include <sys/utsname.h> int uname(struct utsname *buf);
호스트 정보 얻기(계속) – uname(2) utsname 구조체 struct utsname { char sysname[SYS_NMLN]; char nodename[SYS_NMLN]; char release[SYS_NMLN]; char version[SYS_NMLN]; char machine[SYS_NMLN]; char domainname[SYS_NMLN]; };
호스트 정보 얻기(계속) – uname(2) utsname 구초체의 멤버 Member Description sysname 운영체제의 이름 nodename 호스트 이름 release 시스템의 릴리즈 수준 version 시스템의 버전 번호 machine 시스템의 하드웨어 타입 domainname NIS/YP 도메인 이름
호스트에 대한 정보 얻기(계속) 예제 9.1 uname.c - uname(2) 함수 초기화 uname(2)함수 호출 utsname구조체 접근 호스트 정보 출력
호스트 정보 얻기(계속) 초기화 uname(2)함수 호출 Line15 : struct utsname u_name; Line17 : z = uname(&u_name)
호스트 정보 얻기(계속) 구조체에 접근하여 호스트 정보 출력 Line25~36 : printf(“ sysname[] = ‘%s’;\n”, u_name.sysname); printf(“ nodename[] = ‘%s’;\n”, u_name. nodename); printf(“ release[] = ‘%s’;\n”, u_name. release); printf(“ version[] = ‘%s’;\n”, u_name. version); printf(“ machine[] = ‘%s’;\n”, u_name. machine); printf(“ domainname[] = ‘%s’;\n”, u_name. domainname);
호스트 정보 얻기(계속) 실행 결과 $ ./uname sysname[] = 'Linux'; nodename[] = 'syssw.hannam.ac.kr'; release[] = '2.2.14'; version[] = '#1 SMP Sun Jun 25 16:07:10 KST 2000'; machine[] = 'i686'; domainname[] = '(none)';
호스트네임 얻기– gethostname(2) 현재 호스트 네임을 얻는다. 함수 원형 에러 처리 성공 : 음수가 아닌 정수 반환 에러 : –1을 반환하고 errno를 설정 #include <unistd.h> int gethostname(char *name, size_t len);
도메인 네임 얻기 – getdomainname(2) 호스트의 NIS 도메인 네임을 기록 함수 원형 에러 처리 성공 : 음수가 아닌 정수 반환 에러 : –1을 반환하고 errno를 설정 #include <unistd.h> int getdomainname(char *name, size_t len);
호스트네임과 도메인 네임 얻기 예제 9-2 gethostn.c 초기화 gethostname(2)함수 호출 호스트네임 출력 getdomainname(2)함수 호출 도메인 네임 출력
호스트네임과 도메인 네임 얻기(계속) 초기화 gethostname(2) 함수 호출 호스트네임 출력 Line13 : int z; Line14 : char buf[32]; gethostname(2) 함수 호출 Line16 : z = gethostname(buf, sizeof buf); 호스트네임 출력 Line24 : printf(“host name = ‘%s’\n”,buf);
호스트네임과 도메인 네임 얻기(계속) getdomainname(2)함수 호출 도메인 네임 출력 Line26 : z = getdomainname(buf,sizeof buf); 도메인 네임 출력 Line34 : printf(“domain name = ‘%s’\n”,buf);
호스트네임과 도메인 네임 얻기(계속) 실행 결과 $ ./gethostn host name = 'syssw.hannam.ac.kr' domain name = '(none)'
원격지 주소 분석 서버/클라이언트 프로그램 주소와 포트번호를 결정하기 위해 네트워크 정보와 관련된 데이터베이스 함수 사용 /etc/resolv, /etc/hosts, /etc/nsswitch.conf NIS(Network Information Services) DNS(Domain Name Service) IP 주소를 이용한 주소 분석 도메인 네임을 이용한 주소 분석
원격지 주소 분석(계속) 에러 검출 errno에 세팅되지 않고 h_errno에 세팅된다. 원형 #include <netdb.h> extern int h_errno;
원격지 주소 분석(계속) h_errno 에러 사용 함수 h_errno를 인수로 사용하는 함수 gethostbyname(3) gethostbyaddr(3) h_errno를 인수로 사용하는 함수 herror(3) hstrerror(3)
원격지 주소 분석(계속) Error code Error Macro Description HOST_NOT_FOUND 호스트 이름을 알 수 없다 NO_ADDRESS IP 주소가 없다. NO_DATA NO_ADDRESS와 동일 NO_RECOVERY 회수 불가능한 네임서버 에러 TRY_AGAIN 나중에 다시 시도
원격지 주소 분석(계속) gethostbyname(3) 함수 함수 원형 에러처리 호스트 데이터베이스 정보를 수집 실패 시 널(null) 포인터를 반환 h_errno 에 에러 원인을 포함 #include <netdb.h> extern int h_error; struct hostent *gethostbyname(const char *name);
원격지 주소 분석(계속) hostent 구조체 struct hostent { char *h_name; char **h_aliases; char h_addrtype char h_length; char **h_addr_list; };
주소 형태(IPv4 : AF_INET , IPv6 : AF_INET6) 원격지 주소 분석(계속) hostent 구조체 멤버 Member Description h_name 호스트의 공식적 이름 h_aliases 호스트의 별명을 배열의 포인터로 반환 h_addrtype 주소 형태(IPv4 : AF_INET , IPv6 : AF_INET6) h_length 주소길이 (IPv4 : 4, IPv6 : 16) h_addr_list IP 주소를 배열의 포인터로 반환 (IPv4 : 각 포인터는 4 바이트 IP 주소를 가리킨다.
원격지 주소 분석(계속) 예제 9.4 lookup.c - gethostbyname(3) 함수 초기화 hostent구조체 접근 호스트 정보 출력
원격지 주소 분석(계속) 초기화 gethostbyname(3)함수 호출 Line15 : extern int h_errno; Line19 : int x, x2; Line20 : struct hostent *hp; gethostbyname(3)함수 호출 Linet26 : hp = gethostbyname(argv[x]); if ( !hp ){ /* Report lookup failure */ fprintf(stderr "%s: host '%s'", hstrerror(h_errno), argv[x]); continue; }
원격지 주소 분석(계속) 구조체에 접근하여 호스트 정보 출력 Line40 : printf(“ Officially:\t%s\n”, hp ->h_name); Line46 : fputs(“ Aliases:\t”, stdout); for (x2=0; hp ->h_aliases[x2];++x2){ if ( x2) fputs(“, “,stdout); fputs(hp ->h_aliases[x2],stdout); }
원격지 주소 분석(계속) Line49 : printf(“ Type:\t\t%s\n”, hp ->h_addrtype == AF_INET ? “AF_INET” : “AF_INET6”); Line53 : if ( hp ->h_addrtype == AF_INET) { for ( x2=0; hp ->h_addr_list[x2]; ++x2) printf(“ Address:\t%s\n”, inet_ntoa( *(struct in_addr *) hp ->h_addr_list[x2]));
$ ./lookup www.lwn.net sunsite.unc.edu ftp.redhat.com 원격지 주소 분석(계속) 실행 결과 $ ./lookup www.lwn.net sunsite.unc.edu ftp.redhat.com Host www.lwn.net : Officially: lwn.net Aliases: www.lwn.net Type: AF_INET Address: 216.40.34.70 Host ftp.redhat.com : Officially: ftp.redhat.com Aliases: Type: AF_INET Address: 63.240.14.64 Address: 216.148.218.201 Address: 63.240.14.63 Address: 216.148.218.192 Address: 63.240.14.62 Address: 216.148.218.202 Host sunsite.unc.edu : Officially: sunsite.unc.edu Aliases: Type: AF_INET Address: 152.2.210.81
원격지 주소 분석(계속) gethostbyaddr(3) 함수 함수 원형 특정한 IP 주소를 가지는 호스트를 검사 서버상에서 클라이언트의 호출 위치 파악 함수 원형 #include <sys/socket> Struct hostent *gethostbyaddr( const char *addr, /* Input address */ int len, /* Address length */ int type); /* Address type */
원격지 주소 분석(계속) 예제 9.5 srvr2.c – gethostbyaddr(3) 함수 초 기 화 로그파일 열기 로그파일 기록(2) 서버소켓생성 Client에 날짜 출력 로그 파일 기록(1) 연결 종료
원격지 주소 분석(계속) 초기화 Line35 : int z; char *srvr_addr = NULL; char *srvr_port = "9099"; struct sockaddr_in adr_srvr;/* AF_INET */ struct sockaddr_in adr_clnt;/* AF_INET */ int len_inet; /* length */ int s; /* Socket */ int c; /* Client socket */ int n; /* bytes */ time_t td; /* Current date&time */ char dtbuf[128]; /* Date/Time info */ FILE *logf; /* Log file for the server */ struct hostent *hp; /* Host entry ptr */
원격지 주소 분석(계속) 로그파일 열기 로그파일 기록(1) Line52 : if ( !(logf = fopen("srvr2.log","w")) ) bail("fopen(3)"); 로그파일 기록(1) Line138 : fprintf(logf, "Client %s:", inet_ntoa(adr_clnt.sin_addr));
원격지 주소 분석(계속) 서버 주소 설정 서버 포트 설정 Line62 : if ( argc >= 2 ) /* Addr on cmdline: */ srvr_addr = argv[1]; else /* Use default address: */ srvr_addr = "127.0.0.1"; if ( argc >= 3 ) srvr_port = argv[2];
원격지 주소 분석(계속) gethostbyaddr(3) 함수 호출 로그파일 기록(2) Line142 : hp = gethostbyaddr( (char *)&adr_clnt.sin_addr, sizeof adr_clnt.sin_addr, adr_clnt.sin_family); 로그파일 기록(2) Line151 : fprintf(logf," %s", hp->h_name);
원격지 주소 분석(계속) 클라이언트에 날짜 출력 연결종료 Line158 : time(&td); n = (int) strftime(dtbuf,sizeof dtbuf, "%A %b %d %H:%M:%S %Y", localtime(&td)); 연결종료 Line173 : close(C);
원격지 주소 분석(계속) 실행 결과 서버 실행 로컬에서 실행 bk21.hannam.ac.kr 에서 실행 % ./srvr2 % telnet localhost 9099 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Wednesday Apr 11 19:21:31 2001 Connection closed by foreign host. % telnet syssw.hannam.ac.kr 9099 Trying 203.247.40.32... Connected to syssw.hannam.ac.kr. Escape character is '^]'. Wednesday Apr 11 19:26:56 2001 Connection closed by foreign host.
원격지 주소 분석(계속) 실행 결과 % cat srvr2.log Client 127.0.0.1: localhost Client 203.247.40.32: syssw.hannam.ac.kr Client 203.247.40.166: bk21.hannam.ac.kr
원격지 주소 분석(계속) sethostent(3) 함수 함수 원형 인자 네임 서버의 질의 실행을 제어 TRUE : TCP/IP 소켓을 이용 FALSE : UDP 데이터그램을 사용 #include <netdb.h> void sethostent(int stayopen);
원격지 주소 분석(계속) 예제 9.6 lookup2.c 예제 9.4의 lookup.c 와 동일 네임 서버를 제어하는 sethostent(3) 함수를 사용
원격지 주소 분석(계속) 실행 결과 % diff -c lookup.c lookup2.c *** lookup.c Sun Sep 5 07:02:14 1999 --- lookup2.c Tue Apr 10 14:25:40 2001 *************** *** 1,6 **** /* lookup.c: * ! * Example of gethostbyname(3) : */ #include <stdio.h> #include <unistd.h> --- 1,7 ---- ! * Example of gethostbyname(3), ! * using sethostent(3) : *** 14,23 **** --- 15,29 ---- extern int h_errno; + #define TRUE 1 + #define FALSE 0 + int main(int argc,char **argv) { int x, x2; struct hostent *hp; + sethostent(FALSE); for ( x=1; x<argc; ++x ) { /*
원격지 주소 분석(계속) endhostent(3) 함수 함수 원형 sethostent(3) 함수 호출에 의한 네임서버의 연결 해제 함수 원형 #include <netdb.h> void endhostent(void);
요약