2

We are writing an embedded application code and validating a string for a valid IPv4 format. I am successfully able to do so using string tokenizer but now I need to convert the integers to Host-To-Network order using htonl() function.

Since it an embedded application I cannot include network header and library just to make use of htonl() function.

Is there any way / non-network header in C++ by which I can avail htonl() functionality?

Programmer
  • 8,303
  • 23
  • 78
  • 162

2 Answers2

3

From htonl()'s man page:

The htonl() function converts the unsigned integer hostlong from host byte order to network byte order.

Network byte order is actually just big endian.

All you need to do is write (or find) a function that converts an unsigned integer to big endian and use it in place of htonl. If your system is already in big endian than you don't need to do anything at all.


You can use the following to determine the endianness of your system:

int n = 1;
// little endian if true
if(*(char *)&n == 1) {...}

Source


And you can convert a little endian uint32_t to big endian using the following:

uint32_t htonl(uint32_t x) {
    unsigned char *s = (unsigned char *)&x;
    return (uint32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
}

Source

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Increasingly Idiotic
  • 5,700
  • 5
  • 35
  • 73
  • Unfortunately, checking the host byte order like that is implementation defined behaviour; while it will probably always work as intended I'd try to avoid code like that. – Erlkoenig May 04 '18 at 07:03
1

You don't strictly need htonl. If you have the IP address as individual bytes like this:

uint8_t a [4] = { 192, 168, 2, 1 };

You can just send these 4 bytes, in that exact order, over the network. That is unless you specifically need it as a 4 byte Integer, which you probably don't, since you presumably are not using sockaddr_in & friends.

If you already have the address as a 32 bit integer in host byte order, you can obtain a like this:

uint32_t ip = getIPHostOrder();
uint8_t a [4] = { (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF };

This has the advantage of not relying on implementation defined behaviour and being portable.

Erlkoenig
  • 2,664
  • 1
  • 9
  • 18
  • Maybe I am dumb for not seeing it, but how does this work on big and little endian systems? – Increasingly Idiotic May 04 '18 at 05:16
  • Thanks - but mine's code is a function returning in Host-Tio-Netwrok format - so upper interfaces layer are writing the value – Programmer May 04 '18 at 05:23
  • @Erlkoenig Doesn't this still depend on a certain host byte order? – Increasingly Idiotic May 04 '18 at 05:35
  • 1
    No, it should work regardless of host order. htonl is actually just a dirty little trick to allow using sockaddr_in. If you can send individual bytes (like the a array) directly to the network interface, you don't need htonl (and htons etc). – Erlkoenig May 04 '18 at 05:37