Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I change the byte order (from network to host, and vice versa) of an IPV6 address?

I am aware of ntoh{s,l} and hton{s,l}, which work on integers of 2 and 4 bytes. Now, I am facing the problem to translate an IPv6 address, which is 16 bytes long.

Is there a ready-made function for that purpose?

TIA, Jir

like image 433
Jir Avatar asked Dec 28 '22 23:12

Jir


2 Answers

I'm not sure that ntoh and hton are relevant in IPv6. You don't have a native 128-bit type, do you?

According to http://www.mail-archive.com/[email protected]/msg00195.html:

IPv6 addresses are expected to be representd in network byte order whenever they are in binary form (on the wire, on a host, in a router, etc). Among other places, see RFC 2553, section 3.2.

From RFC 2553:

3.2 IPv6 Address Structure

A new in6_addr structure holds a single IPv6 address and is defined as a result of including :

struct in6_addr {
    uint8_t  s6_addr[16];      /* IPv6 address */
};

This data structure contains an array of sixteen 8-bit elements, which make up one 128-bit IPv6 address. The IPv6 address is stored in network byte order.

The structure in6_addr above is usually implemented with an embedded union with extra fields that force the desired alignment level in a manner similar to BSD implementations of "struct in_addr". Those additional implementation details are omitted here for simplicity.

An example is as follows:

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
like image 198
sourcenouveau Avatar answered May 13 '23 02:05

sourcenouveau


Warning: If the C pre-processor (eg, cpp) is replacing every instance of s6_addr with _S6_un._S6_u8, verbatim, then be sure to only use the value of s6_addr in proper context. For example, you mustn't name a function, datatype, or prototype as 's6_addr' because 'void *s6_addr();' would produce 'void *_S6_un._S6_u8();', which is invalid syntax.

Notice that this code does not compile:

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();

So that #define has some side effects to be aware of.

Is there a way to implement this without the side effects?

like image 20
Eric Wheeler Avatar answered May 13 '23 02:05

Eric Wheeler