Search code examples
cgethostbyname

gethostbyname - h_addr_list incorrect first bit


As the title states that data I am getting back from gethostbyname seems to have a mangled first bit.

Here is a short example:

struct hostent* host=  gethostbyname("indiana.cs.rit.edu");

if (!host)
    exit(-1);


printf("%d.%d.%d.%d\n", (host->h_addr_list[0][0]),
                        (host->h_addr_list[0][1]),
                        (host->h_addr_list[0][2]),
                        (host->h_addr_list[0][3]));


printf("%d.%d.%d.%d\n",UP(host->h_addr_list[0][0]),
                       UP(host->h_addr_list[0][1]),
                       UP(host->h_addr_list[0][2]),
                       UP(host->h_addr_list[0][3]));

Where UP is defined as

#define UP(X) (((int)X) & 0XFF)

The output of the above code is:

-127.21.37.10 and 129.21.37.10.

Now I know I should be using inet_ntoa to get my char* version of the IP address. However, does anyone know why my first byte is mangled? Since I am getting back a char** from host->h_addr_list my first [] should deference to the first address where the second [] should dereference to the actual char. given that the char is 1byte, why do I have to perform an bitwise operator to clear out the mangled bit?

Adding to the layer of confusion is why I am getting -127 or 129.

For example, in binary my 129 for one byte should look like..

1000 0001

However, based on the value of -127 it suggest that my underlying binary value is.

1111 1111

Now, where I am really confused is how the bitwise operator of 0XFF (1111 1111) is returning 129 since what I am seeing it should return 255 for unsigned or -127 for signed. Where is the extra data coming from?

Thanks for the help in advance.


Solution

  • host->h_addr_list[0][0] is getting sign extended into a signed int when you use %d with it.

    If you were to do:

    printf("%d.%d.%d.%d\n", (unsigned char)(host->h_addr_list[0][0]),
                            (unsigned char)(host->h_addr_list[0][1]),
                            (unsigned char)(host->h_addr_list[0][2]),
                            (unsigned char)(host->h_addr_list[0][3]));
    

    Then you wouldn't have the problem.

    In two's complement (8 bit) 129 and -127 have the same bit pattern and your analysis is wrong.

    11111111 is -1 in 8 bit signed two's complement (not -127) and the range of a signed 8 bit number is -128 to 127.

    1000000 = -128  (128 unsigned)
    1000001 = -127  (129 unsigned)
    1000010 = -126  (130 unsigned) (etc)