0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Description | |
4bit Version | 8bit Traffic class | 20bit Flow labal | ↑↓8 bytes | ↑↓40 bytes(IPv6 header size) | |||||||||||||||||||||||||||||
16-bit Payload length | 8-bit Next header | 8bit Hop limit | |||||||||||||||||||||||||||||||
128bit Source address | ↑↓32 bytes | ||||||||||||||||||||||||||||||||
128bit Destination address | |||||||||||||||||||||||||||||||||
nexthdr | hdrlen | extension-header | ↑↓IPv6 extension header size | ↑↓Variable size | |||||||||||||||||||||||||||||
~ | |||||||||||||||||||||||||||||||||
nexthdr | hdrlen | extension-header | |||||||||||||||||||||||||||||||
~ | |||||||||||||||||||||||||||||||||
extension-header ... | |||||||||||||||||||||||||||||||||
Upper layer (ICMP/UDP/TCP/SCTP/AH/ESP/IPCOMP/...) | ↑↓Upper layer protocol |
주소유형 | 프리픽스 | 관련 C macro 또는 전역상수 | 비고(참고) |
미지정(Unspecified) | ::/128 | IN6_IS_ADDR_UNSPECIFIED(a), IN6ADDR_ANY_INIT, struct in6_addr in6addr_any | ![]() ![]() |
루프백(Lookback) | ::1/128 | IN6_IS_ADDR_LOOPBACK(a), IN6ADDR_LOOPBACK_INIT, struct in6_addr in6addr_loopback | ![]() ![]() |
IPv4 호환 IPv6 주소(IPv4-compatible IPv6 address) | ::<IPv4-address>/96, Ex) ::123.123.123.123 | IN6_IS_ADDR_V4COMPAT(a) | deprecated by ![]() ![]() |
IPv4 맵핑 IPv6 주소(IPv4-mapped IPv6 address) | ::ffff:<IPv4-address>/96, Ex) ::ffff:123.123.123.123 | IN6_IS_ADDR_V4MAPPED(a) | ![]() ![]() |
Well Known Prefix (IPv4-IPv6 Translation) | 64:ff9b::/96 | ![]() ![]() | |
Well Known Prefix (Local-Use IPv4-IPv6 Translation) | 64:ff9b:1::/48 | ![]() ![]() | |
Discard-Only Address Block | 100::/64 | ![]() ![]() | |
IETF Protocol Assignments | 2001::/23 | ![]() ![]() | |
TEREDO | 2001::/32 | ![]() ![]() ![]() ![]() | |
Port Control Protocol Anycast | 2001:1::1/128 | ![]() ![]() | |
Traversal Using Relays around NAT Anycast | 2001:1::2/128 | ![]() ![]() | |
Benchmarking | 2001:2::/48 | ![]() ![]() ![]() ![]() | |
AMT | 2001:3::/32 | ![]() ![]() | |
AS112-v6 | 2001:4:112::/48 | ![]() ![]() | |
Deprecated (previously ORCHID) | 2001:10::/28 | ![]() ![]() | |
ORCHIDv2 | 2001:20::/28 | ![]() ![]() | |
문서에만 사용할 목적의 전역 유니캐스트(Global unicast for document only) | 2001:db8::/32 | ![]() ![]() | |
6to4 | 2002::/16 | ![]() ![]() | |
Direct Delegation AS112 Service | 2620:4f:8000::/48 | ![]() ![]() | |
로컬 유니캐스트(Local unicast, Unique-Local) | fc00::/7 | ![]() ![]() ![]() ![]() | |
링크로컬 유니캐스트(Link-Local unicast) | fe80::/10 | IN6_IS_ADDR_LINKLOCAL(a) | ![]() ![]() ![]() ![]() |
사이트로컬 유니캐스트(Site-Local unicast) | fec0::/10 | IN6_IS_ADDR_SITELOCAL(a) | ![]() ![]() ![]() ![]() |
멀티캐스트(Multicast) | ff00::/8 | IN6_IS_ADDR_MULTICAST(a), IN6_IS_ADDR_MC_NODELOCAL(a), IN6_IS_ADDR_MC_LINKLOCAL(a), IN6_IS_ADDR_MC_SITELOCAL(a), IN6_IS_ADDR_MC_ORGLOCAL(a), IN6_IS_ADDR_MC_GLOBAL(a) | ![]() ![]() ![]() ![]() |
전역 유니캐스트(Global unicast) | 위의 유형을 제외한 나머지 모든 비트 | ![]() ![]() |
7bits | 1bit | 40bits | 16bits | 64bits |
1111 110 (fc00::/7) | L | Global ID | Subnet ID | Interface ID |
10bits | 54bits | 64bits |
1111 1110 10 (fe80::/10) | 0 | Interface ID |
MAC Address (EUI-48) | |||||
OUI (Organizationally Unique Identifier) | NIC(Network Interface Controller) Specific | ||||
0110 1100 | 0110 0010 | 0110 1101 | 1010 1001 | 0111 1110 | 1101 0000 |
(6C) | (62) | (6D) | (A9) | (7E) | (D0) |
상위 24bits | Mark 16bits (FF FE) | 하위 24bits | |||||
OUI (Organizationally Unique Identifier) | NIC(Network Interface Controller) Specific | ||||||
0110 1100 | 0110 0010 | 0110 1101 | 1111 1111 | 1111 1110 | 1010 1001 | 0111 1110 | 1101 0000 |
(6C) | (62) | (6D) | (FF) | (FE) | (A9) | (7E) | (D0) |
EUI-64 | |||||||
상위 24bits | Mark 16bits (FF FE) | 하위 24bits | |||||
상위(MSB) 7번째 bit set | |||||||
0110 1110 | 0110 0010 | 0110 1101 | 1111 1111 | 1111 1110 | 1010 1001 | 0111 1110 | 1101 0000 |
(6E) | (62) | (6D) | (FF) | (FE) | (A9) | (7E) | (D0) |
IPv6 Link-local address by EUI-64 | |||||||||||||||
Prefix (fe80::/10) | 0 | 상위 24bits | Mark 16bits (FF FE) | 하위 24bits | |||||||||||
1111 1110 | 1000 0000 | 0000 0000 | 0000 0000 | 0000 0000 | 0000 0000 | 0000 0000 | 0000 0000 | 0110 1110 | 0110 0010 | 0110 1101 | 1111 1111 | 1111 1110 | 1010 1001 | 0111 1110 | 1101 0000 |
(FE) | (80) | (00) | (00) | (00) | (00) | (00) | (00) | (6E) | (62) | (6D) | (FF) | (FE) | (A9) | (7E) | (D0) |
10bits | 54bits | 64bits |
1111 1110 11 (fec0::/10) | Subnet ID | Interface ID |
8bits | 4bits | 4bits | 112bits |
1111 1111 | flags | scope | Group ID |
8bits | 4bits | 4bits | 8bits | 8bits | 64bits | 32bits |
1111 1111 | flags | scope | reserved(MUST be zero) | plen | network prefix | group ID |
0(항상 zero) | R(![]() ![]() | P(![]() ![]() | T(![]() ![]() |
값 | 설명 | 비고(참고) |
0 | 예약 (reserved) | ![]() ![]() ![]() ![]() |
1 | 로컬 범위의 인터페이스 (interface-local scope) | ![]() ![]() ![]() ![]() |
2 | 로컬 범위의 링크 (link-local scope) | ![]() ![]() ![]() ![]() |
3 | 예약 (reserved) / 로컬 범위의 서브넷 (subnet) / Realm-Local scope | ![]() ![]() ![]() ![]() |
4 | 로컬 범위의 관리 (admin-local scope) | ![]() ![]() ![]() ![]() |
5 | 로컬 범위의 사이트 (site-local scope) | ![]() ![]() ![]() ![]() |
6 | 할당되지 않음 (unassigned) | |
7 | 할당되지 않음 (unassigned) | |
8 | 로컬 범위의 조직 (organization-local scope) | ![]() ![]() ![]() ![]() |
9 | 할당되지 않음 (unassigned) | |
10 | 할당되지 않음 (unassigned) | |
11 | 할당되지 않음 (unassigned) | |
12 | 할당되지 않음 (unassigned) | |
13 | 할당되지 않음 (unassigned) | |
14 | 글로벌 범위 (global scope) | ![]() ![]() ![]() ![]() |
15 | 예약 (reserved) | ![]() ![]() ![]() ![]() |
iec_sockaddr_t s_remote, s_bind; iec_socket_t s_socket; iec_const_string_t s_remote_address; iec_socket_t s_socket; s_remote_address = "http://test.minzkn.com:80/index.php"; /* 먼저 remote 주소의 sockaddr을 설정한다. (node는 uri를 허용한다) */ if(iec_xapi_resolve_sockaddr(AF_UNSPEC, (iec_sockaddr_t *)(&s_remote), s_remote_address, iec_xapi_int_const(80), def_iec_true) == def_iec_true) { /* 설정된 s_remote의 family를 bind address family 로 결정한다. (node는 uri를 허용하지 않는다) */ if(iec_xapi_resolve_sockaddr(s_remote.ss.ss_family, (iec_sockaddr_t *)(&s_bind), def_iec_null_string, iec_xapi_int_const(0), def_iec_false) != def_iec_error) { /* 결정된 bind address family에 맞는 소켓을 연다. */ s_socket = iec_xapi_socket(s_bind.ss.ss_family, SOCK_STREAM, IPPROTO_TCP); if(s_socket != def_iec_invalid_socket) { if(iec_xapi_bind(s_socket, (iec_sockaddr_t *)(&s_bind)) == def_iec_true) { if(iec_xapi_connect(s_socket, (iec_sockaddr_t *)(&s_remote), s_timeout) == def_iec_true) { /* connected */ } } s_socket = iec_xapi_closesocket(s_socket); } } }
iec_const_string_t s_bind_address; iec_int_t s_bind_port; iec_sockaddr_t s_sockaddr_bind, s_sockaddr_accept; iec_socket_t s_listen_socket, s_accept_socket; iec_socklen_t s_socklen; if(iec_xapi_resolve_sockaddr(AF_UNSPEC, (iec_sockaddr_t *)(&s_sockaddr_bind), s_bind_address, s_bind_port, def_iec_false) == def_iec_true) { s_listen_socket = iec_xapi_socket(s_sockaddr_bind.ss_family, SOCK_STREAM, IPPROTO_TCP); if(s_listen_socket != def_iec_invalid_socket) { if(iec_xapi_bind(s_listen_socket, (iec_sockaddr_t *)(&s_sockaddr_bind), (iec_socklen_t)sizeof(s_sockaddr_bind)) == def_iec_true) { if(iec_xapi_listen(s_listen_socket, def_iec_max_backlog) == def_iec_true) { for(; /* exit condition */ ;) { s_socklen = (iec_socklen_t)sizeof(s_sockaddr_accept); s_accept_socket = iec_xapi_accept(s_listen_socket, (iec_sockaddr_t *)(&s_sockaddr_accept), (iec_socklen_t *)(&s_socklen), 0/* timeout */); if(s_accept_socket != def_iec_invalid_socket) { if(s_sockaddr_accept.ss_family == AF_INET) { /* IPv4 accept process */ } else if(s_sockaddr_accept.ss_family == AF_INET6) { /* IPv6 accept process */ } else { /* Unspec accept process */ } iec_xapi_closesocket(s_accept_socket); } else { iec_xapi_load_balance(); } } } } iec_xapi_closesocket(s_listen_socket); } }
struct ip_mreq { struct in_addr imr_multiaddr; /* IP multicast address of group */ struct in_addr imr_interface; /* local IP address of interface */ }; setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (struct ip_mreq *)(&r), sizeof(struct ip_mreq));
struct ipv6_mreq { /* IPv6 multicast address of group */ struct in6_addr ipv6mr_multiaddr; /* local IPv6 address of interface */ int ipv6mr_ifindex; }; setsockopt(socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, (struct ipv6_mreq *)(&r), sizeof(struct ipv6_mreq));
int s_ttl; /* unicast ttl */ setsockopt(socket, IPPROTO_IP, IP_TTL, &s_ttl, sizeof(s_ttl)); /* multicast ttl */ setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, &s_ttl, sizeof(s_ttl));
int s_hops; /* unicast ttl */ setsockopt(socket, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &s_hops, sizeof(s_hops)); /* multicast ttl */ setsockopt(socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &s_hops, sizeof(s_hops));
EPRT<space><d><net-prt><d><net-addr><d><tcp-port><d> 여기서 <d>는 구분자로써 '|'을 사용하는것으로 되어 있습니다. <net-prt>는 '1'은 IPv4를 의미하고 '2'는 IPv6를 의미합니다. EPSV<space><net-prt> 229 Entering Extended Passive Mode (|||<tcp-port>|) EPSV에 대한 응답형식은 EPRT와 유사합니다. EPSV의 <net-prt>에는 '1', '2', 'ALL'이 사용될수 있다고 합니다. 하지만 실험결과 'ALL'은 제대로 동작하지 않는 경우가 많았습니다.
/* s_ipv6hdr : IPv6 Header에 대한 pointer 입력 s_nexthdr_ptr : nexthdr 가 명시된 부분에 대한 pointer 입력 반환 : IPv6 extension header 의 크기 반환 */ size_t hwport_ipv6_extension_header_size(struct ipv6hdr *s_ipv6hdr, u8 *s_nexthdr_ptr) { size_t s_offset = (size_t)0; /* payload start offset == 40 */ u8 *s_u8_ptr = (u8 *)(&s_ipv6hdr[1]); /* payload start entry */ u8 s_nexthdr = s_ipv6hdr->nexthdr; struct ipv6_opt_hdr *s_exthdr; size_t s_exthdr_size; while(ipv6_ext_hdr(s_nexthdr)) { if(s_nexthdr == NEXTHDR_NONE) { break; } if(unlikely((s_offset + sizeof(struct ipv6_opt_hdr)) > ((size_t)s_ipv6hdr->payload_len))) { /* invalid extension header coding */ s_offset = (size_t)s_ipv6hdr->payload_len; s_nexthdr = NEXTHDR_NONE; break; } s_exthdr = (struct ipv6_opt_hdr *)(&s_u8_ptr[s_offset]); if(s_nexthdr == NEXTHDR_FRAGMENT) { s_exthdr_size = (size_t)8u; } else if(s_nexthdr == NEXTHDR_AUTH) { /* AH header */ s_exthdr_size = (s_exthdr->hdrlen + 2) << 2; } else { s_exthdr_size = ipv6_optlen(s_exthdr); } if(unlikely((s_offset + s_exthdr_size) > ((size_t)s_ipv6hdr->payload_len))) { /* invalid extension header size coding */ s_offset = (size_t)s_ipv6hdr->payload_len; s_nexthdr = NEXTHDR_NONE; break; } s_nexthdr = s_exthdr->nexthdr; s_offset += s_exthdr_size; } if(s_nexthdr_ptr != ((u8 *)0)) { *s_nexthdr_ptr = s_nexthdr; } return(s_offset); } /* s_ipv6hdr : IPv6 Header에 대한 pointer 입력 s_transport_size_ptr : Transport layer 의 크기를 반환 (IPv6 Header 및 IPv6 extension header를 제외한 IPv6 payload 의 크기) s_nexthdr_ptr : nexthdr 가 명시된 부분에 대한 pointer 입력 반환 : Transport layer에 대한 pointer 반환 */ void *hwport_ipv6_transport_entry(struct ipv6hdr *s_ipv6hdr, size_t *s_transport_size_ptr, u8 *s_nexthdr_ptr) { u8 *s_u8_ptr = (u8 *)s_ipv6hdr; size_t s_header_size = sizeof(struct ipv6hdr); size_t s_ext_header_size = hwport_ipv6_extension_header_size(s_ipv6hdr, s_nexthdr_ptr); if(s_transport_size_ptr != ((size_t *)0)) { *s_transport_size_ptr = ((size_t)s_ipv6hdr->payload_len) - s_ext_header_size; } return((void *)(&s_u8_ptr[s_header_size + s_ext_header_size])); } /* 사용예 */ struct sk_buff *skb; /* 인입된 패킷을 담고 있는 skbuff pointer */ size_t s_ipv6h_size = sizeof(struct ipv6hdr); /* IPv6 Header 크기 (IPv6 extension header는 제외) */ struct ipv6hdr *s_ipv6hdr = ip_hdr(skb); /* skb로부터 IPv4/IPv6 Header 위치 pointer */ u8 s_nexthdr; /* IPv6 externsion header 를 건너뛰고 마지막 nexthdr */ size_t s_ipv6h_ext_size; /* IPv6 extension header 크기 */ void *s_transport_entry; /* Transport layer entry pointer */ size_t s_transport_size; /* Transport layer 크기 */ ASSERT(s_ipv6hdr->version == 6); s_ipv6h_ext_size = hwport_ipv6_extension_header_size(s_ipv6hdr, (u8 *)(&s_nexthdr)); s_transport_entry = hwport_ipv6_transport_entry(s_ipv6hdr, (size_t *)(&s_transport_size), (u8 *)(&s_nexthdr)); if(s_nexthdr == IPPROTO_TCP) { struct tcphdr *s_tcphdr = (struct tcphdr *)s_transport_entry; } else if(s_nexthdr == IPPROTO_UDP) { } else { ... }