IP(4)

명칭
ip - 인터넷 프로토콜

서식
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> int socket(AF_INET, SOCK_RAW, proto)

설명
IP (은)는, 인터넷 프로토콜 패밀리가 이용하는 트랜스폴트층의 프로토콜입니다. IP 에 근거한, 보다 고위의 프로토콜 (예를 들면, TCP (이)나 UDP ) (을)를 이용하고 있을 때는, IP 레벨로 옵션을 설정할 수 있습니다. 또, 새로운 프로토콜이나 특별한 용도의 어플리케이션을 개발하고 있을 때는, “raw 소켓” (을)를 통해 액세스 할 수도 있습니다.

IP 레벨 의 setsockopt(2) 및 getsockopt(2) 옵션이 몇개인가 있습니다. IP_OPTIONS (은)는, 송신되는 각 패킷의 IP 헤더중에 파묻힌다 IP 옵션을 제공하거나 수신되는 패킷의 헤더부의 옵션을 검사하거나 하기 위해서 사용됩니다. IP 옵션은, 인터넷 패밀리의 모든 소켓 타입으로 사용할 수가 있습니다. 송신된다 IP 옵션의 포맷은, IP 프로토콜의 사양 (RFC-791)으로 결정되어 있습니다. 다만, 1 개(살) 예외가 있습니다. 지정 경로 제어 옵션용의 주소 리스트에는, 게이트웨이 리스트의 선두에, 최초로 패킷이 통과하는 게이트웨이가 포함되어 있는 것이 필요합니다. 최초로 패킷이 통과하는 게이트웨이의 주소는 옵션 리스트로부터 꺼내져 사용되기 전에 적절한 크기로 고쳐집니다. 이전으로 지정된 옵션을 무효로 하려면 , 길이 0 의 버퍼를 사용해 주세요.

    setsockopt(s, IPPROTO_IP, IP_OPTIONS, NULL, 0);

IP_TOS 및 IP_TTL (은)는, SOCK_STREAM 및 SOCK_DGRAM 그리고 이용된다 IP 헤더내의, 서비스 타입 (type-of-service) 필드와 생존 시간 (time-to-live) 필드를 설정하기 위해서 사용됩니다. 예를 들면, 이하와 같이 합니다.

    int tos = IPTOS_LOWDELAY;       /* <netinet/in.h> 참조 */
    setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
    int ttl = 60;                   /* 최대치는 255 */
    setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));

만약, IP_RECVDSTADDR 옵션이 SOCK_DGRAM 소켓으로 유효하게 되어 있었을 경우, recvmsg(2) 시스템 콜은, UDP 다이어그램용의 발송지의 IP 주소를 돌려줍니다. msghdr 구조체의 msg_control 필드는 IP 주소의 뒤에 계속된 cmsghdr 구조몸이 들어온 버퍼에의 포인터가 되어 있습니다. cmsghdr 필드는 이하와 같은 값을 가집니다.

    cmsg_len = sizeof(struct in_addr)
    cmsg_level = IPPROTO_IP
    cmsg_type = IP_RECVDSTADDR

IP_PORTRANGE (은)는, 포트 번호의 범위를 설정하기 위해서 사 됩니다. 이 범위의 로컬 포트 번호 중 하나가, 포트 번호를 지정하지 않았던 (0 이 지정된) 소켓용으로 선택됩니다. 이것은, 이하와 같은 값을 취할 수 있습니다.

IP_PORTRANGE_DEFAULT
    디폴트의 범위의 포트 번호치를 사용합니다. 통상은 IPPORT_RESERVED (으)로부터 IPPORT_USERRESERVED 입니다. 이 값은, sysctl 의 설정, net.inet.ip.portrange.first 및 net.inet.ip.portrange.last (을)를 통해 조정할 수 있습니다.

IP_PORTRANGE_HIGH
    (은)는, 큰 값의 범위의 포트 번호를 사용합니다. 통상은 IPPORT_HIFIRSTAUTO 및 IPPORT_HILASTAUTO 입니다. 이 값은, sysctl의 설정, net.inet.ip.portrange.hifirst 및 net.inet.ip.portrange.hilast (을)를 통해 조정할 수 있습니다.

IP_PORTRANGE_LOW
    (은)는, 작은 값의 범위의 포트 번호를 사용합니다. 통상은, UNIX 시스템상에서 특권을 가진 프로세스에 사용이 한정되고 있습니다. 이 값의 범위는, 통상 IPPORT_RESERVED (으)로부터 1 까지로, 내림차순에 줄지어 있습니다. 이 값의 범위는 sysctl 에서는 설정할 수 없습니다.

  멀티 캐스트 옵션

IP 의 멀티 캐스트는 SOCK_DGRAM 및 SOCK_RAW 형태의 AF_INET 소켓으로, 인터페이스 드라이버가 멀티 캐스트 에 대응하고 있는 네트워크만으로 실시할 수 있습니다.

IP_MULTICAST_TTL 옵션은, 송신되는 멀티 캐스트 데이터 그램의 생존 시간 (TTL) 치를 변경합니다. 이 값을 변경하는 것으로 멀티 캐스트의 범위를 제어할 수 있습니다.

    u_char ttl;	/*  0 에서 255 의 범위.  기본값은 1 */
    setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

TTL 치가 1 의 데이터 그램은, 로컬 네트워크를 넘어 전송 될 것은 없습니다. TTL 치가 0 의 데이터 그램은 어느 네트워크에도 송신됩니다만, 데이터 그램을 보낸 호스트가 발송지의 그룹에 속하고 있어 송신을 실시하는 소켓이 멀티 캐스트 루프 팩을 무효로 하고 있지 않으면 (아래와 같이 참조), 로컬 네트워크에는 송신될지도 모릅니다. TTL 치가 1 보다 큰 데이터 그램은, 로컬 네트워크에 multicast router가 접속되고 있으면, 다른 네트워크에 전송 됩니다.

복수의 인터페이스를 가진 호스트에는, 각 멀티 캐스트 송신은, 최초의 네트워크 인터페이스로부터 행해집니다. IP_MULTICAST_IF 옵션을 사용하면(자), 지정된 소켓으로부터의 다음의 송신을 위해서(때문에) 기본값을 개서일이 생깁니다.

    struct in_addr addr;
    setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr));

여기서,"addr" 는, 로컬 호스트의 사용하고 싶은 인터페이스의 IP 주소입니다. 또는, INADDR_ANY (을)를 지정해, 디폴트의 인터페이스를 나타내도록(듯이)도 할 수 있습니다. 인터페이스의 로컬 IP 주소 및 멀티 캐스트 능력의 유무는, SIOCGIFCONF 및 SIOCGIFFLAGS ioctl 시스템 콜로 얻을 수 있습니다. 보통 어플리케이션에서는 이 옵션을 사용할 필요는 없을 것입니다.

만약, 멀티 캐스트 데이터 그램이 보내 원의 호스트 자신이 속하고 있는 그룹 (발송지의 인터페이스상에 있다) 에 송신된다면, 디폴트에서는 로컬에의 배송용으로, 그 다이어그램의 카피가 IP 층에 의해 루프백 됩니다. IP_MULTICAST_LOOP 옵션은, 송신 호스트에 향후의 데이터 그램을 루프백 하는지 어떤지를 제어하는 권한을 명시적에게 줍니다.

    u_char loop;	/* 0 = 무효, 1 = 유효 (디폴트) */
    setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));

이 옵션은, 자신이 송신한 패킷을 받을 때의 오버헤드를 경감하는 것으로, 1 살의 호스트에 1 개 밖에 실체를 가지지 않는 어플리케이션 (예를 들면, 라우터 demon)의 퍼포먼스를 향상시킵니다. 이 옵션은, 1 살의 호스트상에서 복수의 실체를 가질 수 있는 어플리케이션 (예를 들면, 회의 프로그램)(이)나, 송신원의 호스트가 송신지의 그룹에 속하지 않는 어플리케이션 (예를 들면, 시각 문의 프로그램)에서는 사용되지 않습니다.

TTL 의 초기치를 1 보다 크게 해 송신된 멀티 캐스트 데이터 그램은, 송신원의 인터페이스와는 다른 인터페이스상의 호스트로부터 송신원 의 호스트에 배송될지도 모릅니다. 다만, 송신원이 아닌 (분)편의 인터페이스상에서, 이 호스트가 행선지의 그룹에 속하고 있는 경우입니다. 루프백 컨트롤 옵션은, 이러한 배송에 대해서는 어떤 효력도 가지지 않습니다.

어느 멀티 캐스트 그룹으로부터 송신된 데이터 그램을 받으려면 , 호스트가 그 멀티 캐스트 그룹에 속하고 있는 것이 필요합니다. 어느 멀티 캐스트 그룹에 참가하려면 , IP_ADD_MEMBERSHIP 옵션을 사용합니다.

    struct ip_mreq mreq;
    setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

여기에서는, mreq (은)는 이하와 같은 구조체입니다.

    struct ip_mreq {
        struct in_addr imr_multiaddr; /* 그룹의 IP 멀티 캐스트 주소 */
        struct in_addr imr_interface; /* 인터페이스의 로컬 IP 주소 */
    }

디폴트의 멀티 캐스트 인터페이스를 선택하려면 , imr_interface 하 INADDR_ANY (으)로 합니다. 또, 호스트가 multi-homed로 설정되어 있으면, 특정의 멀티 캐스트 가능한 인터페이스의 IP 주소로 지정하는 것이 필요합니다. 멘바십은, 1 개의 인터페이스에 결합되고 있습니다. 그 때문에, multi-homed host상에서 동작하고 있는 프로그램은, 1 개(살) 이상의 인터페이스상에서 동일한 그룹에 들어갈 필요가 있다 일지도 모릅니다. 1 개의 소켓에 최대 IP_MAX_MEMBERSHIPS (현재는 20) 개의 멘바십을 설정할 수 있습니다.

멤버로부터 빠지려면 , 이하의 함수를 사용합니다.

    struct ip_mreq mreq;
    setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));

여기서, mreq (은)는 멤버에 참가할 때 사용한 것과 같은 값이 들어옵니다. 소켓을 닫거나 프로세스가 종료하거나 했을 경우는 멤버로부터 빠집니다.

  raw IP 소켓

raw IP 소켓은, connection를 가지지 않는 소켓으로, 통상은 sendto(2) (이)나 recvfrom(2) 콜과 함께 사용됩니다. 다만, connect(2) 콜은, 지금부터 흘러 오는 패킷의 발송지를 정하기 위해서(때문에)도 사용됩니다. (이 경우에는, read(2) 혹은 recv(2) , 및 write(2) 혹은 send(2) 시스템 콜이 사용되겠지요. )

proto 하지만 0 의 경우에는, 패킷의 송신에는 디폴트의 프로토콜이다 IPPROTO_RAW 하지만 사용되어 이 프로토콜로 향해 보내져 온 패킷만이 수신됩니다. proto 하지만 0 이 아닌 경우, 그 프로토콜의 번호가 송신 패킷상에서 사용되어 또, 입력 패킷을 필터링 하기 위해서 사용됩니다.

송신 패킷에는, 자동적으로 IP 헤더 (이것은, 발송지 주소 및 소켓이 작성되었을 때의 프로토콜 번호있고 있습니다) 하지만 주어집니다. 다만, IP_HDRINCL 옵션이 설정되어 있을 때는 IP 헤더는 주어지지 않습니다. 수신 패킷은, 완전한 형태의 IP 헤더 및 옵션과 함께 수취됩니다.

IP_HDRINCL (은)는, 데이터와 함께 완전한 IP 헤더가 포함되어 있는 것을 가리켜, SOCK_RAW 형태로 밖에 사용되지 않습니다.

    #include <netinet/in_systm.h>
    #include <netinet/ip.h>
    int hincl = 1;                  /* 1: 온 , 0: 오프 */
    setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl));

이전의 BSD 릴리스와는 달라, 이 프로그램에서는, 모든 IP 헤더 의 필드를 설정하는 것이 필요합니다. 이것에는 다음의 필드 도 포함합니다.

    ip->ip_v = IPVERSION;
    ip->ip_hl = hlen >> 2;
    ip->ip_id = 0;  /* 0 이라고 하는 것은, 커널이 적절한 값을
                       설정해 준다고 하는 것입니다.  */
    ip->ip_off = offset;

헤더의 보내 원의 주소가 INADDR_ANY (으)로 설정되어 있으면(자), 커널이 적절한 주소를 선택합니다.

진단
소켓 조작이 다음과 같은 에러의 어느쪽이든을 돌려주어 실패하는 것이 있습니다.

[EISCONN]
    벌써 접속이 확립된 소켓에 접속을 시도하려고 했을 때나, 발송지 주소를 지정해 데이터 그램을 송신하려고 했을 때에 발송지의 소켓이 벌써 접속되고 있을 때 생깁니다.

[ENOTCONN]
    데이터 그램을 송신하려고 했을 때에, 발송지 주소가 지정되지 않고, 소켓이 아직 접속되어 있지 않을 때에 생깁니다.

[ENOBUFS]
    내부의 데이터 구조로 시스템이 메모리를 다 써 버렸을 때에 생깁니다.

[EADDRNOTAVAIL]
    네트워크 주소를 이용해 소켓을 작성하려고 했지만, 그것을 위한 네트워크 인터페이스가 존재하지 않을 때에 생깁니다.

[EACESS]
    특권이 없는 프로세스에 의해 raw IP 소켓을 작성하려고 했을 때에 생깁니다.

다음과 같은, IP 에 특유의 에러가 IP 의 옵션을 설정하거나 취득하거나 할 때에 생기는 일이 있습니다.

[EINVAL]
    소켓의 옵션명에 불명한 것이 주어졌습니다.

[EINVAL]
    IP 의 옵션필드가 적절한 형태가 되어 있지 않았습니다. 즉, 옵션필드가 최소치보다 짧기도 하고, 주어진 옵션 버퍼보다 길거나 했다고 하는 것입니다.

관련 항목
getsockopt(2), recv(2), send(2), icmp(4), inet(4), intro(4)

역사
ip 프로토콜은, 4.2BSD (으)로부터 등장했습니다.