저는 ntoh{s,l}
과 hton{s,l}
을 알고 있습니다. 2와 4 바이트의 정수에서 작동합니다. 이제 16 바이트 길이의 IPv6 주소를 변환하는 데 문제가 있습니다.IPV6 주소의 바이트 순서 (네트워크에서 호스트로 또는 그 반대로)를 변경하려면 어떻게합니까?
그 목적으로 기성품이 있습니까?
TIA, JIR 내가 ntoh
및 hton
에서 IPv6에 관련된 모르겠어요
저는 ntoh{s,l}
과 hton{s,l}
을 알고 있습니다. 2와 4 바이트의 정수에서 작동합니다. 이제 16 바이트 길이의 IPv6 주소를 변환하는 데 문제가 있습니다.IPV6 주소의 바이트 순서 (네트워크에서 호스트로 또는 그 반대로)를 변경하려면 어떻게합니까?
그 목적으로 기성품이 있습니까?
TIA, JIR 내가 ntoh
및 hton
에서 IPv6에 관련된 모르겠어요
. 네이티브 128 비트 타입이 없습니까? http://www.mail-archive.com/[email protected]/msg00195.html 따르면
는 :
IPv6 주소는 이들이 이진 형태로있을 때마다 네트워크 바이트 순서 에 representd 것으로 예상된다 (라우터에서 호스트에 에 와이어 등) . 다른 곳에서는 RFC 2553, 섹션 3.2를 참조하십시오. RFC 2553 가입일
:
struct in6_addr {
uint8_t s6_addr[16]; /* IPv6 address */
};
이 데이터 : 새로운 된 in6_addr 구조는 하나의 IPv6 주소를 보유 포함의 결과로 정의된다
3.2 IPv6 주소 구조 구조체는 하나의 128 비트 IPv6 주소를 구성하는 16 개의 8 비트 요소의 배열을 포함합니다. IPv6 주소는 네트워크 바이트 순서로 저장됩니다.
위의 in6_addr 구조는 일반적으로 "struct in_addr"의 BSD 구현과 비슷한 방식으로 원하는 정렬 수준을 강제하는 추가 필드가있는 포함 된 통합으로 구현됩니다. 이들 추가적인 구현 세부 사항은 간략화를 위해 여기서는 생략된다. 다음
예는 다음
struct in6_addr { union { uint8_t _S6_u8[16]; uint32_t _S6_u32[4]; uint64_t _S6_u64[2]; } _S6_un; }; #define s6_addr _S6_un._S6_u8
경고 : C 프리 프로세서 (예를 들어, CPP) _S6_un._S6_u8와 s6_addr의 모든 인스턴스를 대체하는 경우, 그대로, 만 반드시 적절한 문맥에서 s6_addr의 값을 사용하십시오. 예를 들어 'void * s6_addr();'이 (가) 있기 때문에 함수, 데이터 유형 또는 프로토 타입의 이름을 's6_addr'으로 지정하면 안됩니다. 유효하지 않은 구문 인 'void * _S6_un._S6_u8();'을 생성합니다. 이 코드는 컴파일되지 않습니다
주의 사항 :
struct in6_addr {
union {
unsigned char _S6_u8[16];
unsigned long _S6_u32[4];
unsigned long long _S6_u64[2];
} _S6_un;
};
#define s6_addr _S6_un._S6_u8
void *s6_addr();
은 그래서 #DEFINE는 인식에 영향을 끼친다.
부작용없이 구현할 수있는 방법이 있습니까?
IPv6에서는 ipv6 주소에 대해 네트워크 주문이 필요합니다. hton과 ntoh는 주소를 코드에 저장 한 방식에서 패킷에 저장해야하는 방식 (또는 그 반대)으로 변환하는 것입니다. 따라서 문제는 코드에 저장 한 방법이됩니다.
또한 코드의 IPv6 주소의 정의 방법 더 바이트 단지 배열 이상을 충족하는 것을 허용 할 수struct in6_addr
{
union
{
__u8 u6_addr8[16];
__u16 u6_addr16[8];
__u32 u6_addr32[4];
} in6_u;
#define s6_addr in6_u.u6_addr8
#define s6_addr16 in6_u.u6_addr16
#define s6_addr32 in6_u.u6_addr32
};
IPv6 주소는, 사용자에게,도 8의 16 비트 값으로 표시된다. 코드에 8 개의 16 비트 값으로 저장된 주소가있는 경우 u6_addr16 [] 배열을 사용하여 패킷에 배치 할 때 각 16 비트 값에 hton을 사용해야하고 각 16을 검색 할 때 ntohs를 사용해야합니다 u6_addr16 []에서 비트 값.
이러한 링크는 도움이됩니다 :
내가 IPv6를 취급하고 내가 좋아하는 뭔가를 사용 순수한 바이너리 형태로 해결 이 :
// Compile with gcc
#include <x86intrin.h>
#include <stdint.h>
#include <arpa/inet.h>
// C99 supports __int128!
typedef unsigned __int128 uint128_t;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define htonll(v) __builtin_bswap64((v))
uint128_t hton128(uint128_t val)
{
// SSE2 is defined if SSSE3.
# if __SSSE3__
// This routine is 100 cycles faster than the routine below.
__m128i m;
__m128i mask;
m = _mm_loadu_si128((__m128i *)&val);
// mask: 0x0f0e0d0c0b0a09080706050403020100
mask = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
_mm_store_si128((__m128i *)&val, _mm_shuffle_epi8(m, mask));
# else
// No SSSE3.. Slowest approach: use pointers to shuffle.
uint64_t *p, *q;
p = (uint64_t *)&val;
q = p + 1;
*p = htonll(*p);
*q = htonll(*q);
{
uint64_t t;
t = *p;
*p = *q;
*q = t;
}
# endif
return val;
}
#endif
이것은 모든 #define에 해당합니다. 당신은 항상 부작용에 매우 조심해야합니다. 함수 이름에 형식 이름이 필요하거나 그렇지 않으면 정확한 의도 된 컨텍스트에서 #define을 사용하지 않으면 항상 결과를 알 수 있습니다. – Pyrocater