-2

I previously posted how to implement a function that will convert an integer to an IP address string. So how would we go vice-versa, that is, given a string (154.111.23.23) that is an address, how can we get that integer back, using no inet functions.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Kris Richards
  • 381
  • 2
  • 4
  • 5

5 Answers5

4

scanf the string into four bytes and add/shift them into a 32 bit integer.

2

Posix.1-2001 provides inet_pton() for this task. There's a couple of ms-windows versions of this too.

Jasen
  • 11,837
  • 2
  • 30
  • 48
1
//No checking of the input    
unsigned int c1,c2,c3,c4;
scanf("%d.%d.%d.%d",&c1,&c2,&c3,&c4);
unsigned long ip = (unsigned long)c4+c3*256+c2*256*256+c1*256*256*256;
printf("The unsigned long integer is %lu\n",ip);

EDIT: For those how are interested on the code produced, GCC is smart enough to replace my multiplication of 256 with shifts left. (In my program I've also called exit):

0x80483d4   <main>:     lea    0x4(%esp),%ecx
0x80483d8   <main+4>:       and    $0xfffffff0,%esp
0x80483db   <main+7>:       pushl  -0x4(%ecx)
0x80483de   <main+10>:      push   %ebp
0x80483df   <main+11>:      mov    %esp,%ebp
0x80483e1   <main+13>:      push   %ecx
0x80483e2   <main+14>:      sub    $0x34,%esp
0x80483e5   <main+17>:      lea    -0x14(%ebp),%eax
0x80483e8   <main+20>:      mov    %eax,0x10(%esp)
0x80483ec   <main+24>:      lea    -0x10(%ebp),%eax
0x80483ef   <main+27>:      mov    %eax,0xc(%esp)
0x80483f3   <main+31>:      lea    -0xc(%ebp),%eax
0x80483f6   <main+34>:      mov    %eax,0x8(%esp)
0x80483fa   <main+38>:      lea    -0x8(%ebp),%eax
0x80483fd   <main+41>:      mov    %eax,0x4(%esp)
0x8048401   <main+45>:      movl   $0x8048520,(%esp)
0x8048408   <main+52>:      call   0x8048320 <scanf@plt>
0x804840d   <main+57>:      mov    -0x8(%ebp),%eax
0x8048410   <main+60>:      mov    %eax,%edx
0x8048412   <main+62>:      shl    $0x8,%edx
    0x8048415   <main+65>:      mov    -0xc(%ebp),%eax
0x8048418   <main+68>:      lea    (%edx,%eax,1),%eax
0x804841b   <main+71>:      mov    %eax,%edx
0x804841d   <main+73>:      shl    $0x8,%edx
0x8048420   <main+76>:      mov    -0x10(%ebp),%eax
0x8048423   <main+79>:      lea    (%edx,%eax,1),%eax
0x8048426   <main+82>:      mov    %eax,%edx
0x8048428   <main+84>:      shl    $0x8,%edx
0x804842b   <main+87>:      mov    -0x14(%ebp),%eax
0x804842e   <main+90>:      lea    (%edx,%eax,1),%eax
0x8048431   <main+93>:      mov    %eax,-0x18(%ebp)
0x8048434   <main+96>:      mov    -0x18(%ebp),%eax
0x8048437   <main+99>:      mov    %eax,0x4(%esp)
0x804843b   <main+103>:     movl   $0x804852c,(%esp)
0x8048442   <main+110>:     call   0x8048330 <printf@plt>
0x8048447   <main+115>:     movl   $0x0,(%esp)
0x804844e   <main+122>:     call   0x8048340 <exit@plt>
Liran Orevi
  • 4,755
  • 7
  • 47
  • 64
0
uint32_t getDecimalValueOfIPV4_String(const char* ipAddress)
{
    uint8_t ipbytes[4]={};
    int i =0;
    int8_t j=3;
    while (ipAddress+i && i<strlen(ipAddress))
    {
       char digit = ipAddress[i];
       if (isdigit(digit) == 0 && digit!='.'){
           return 0;
       }
        j=digit=='.'?j-1:j;
       ipbytes[j]= ipbytes[j]*10 + atoi(&digit);

        i++;
    }

    uint32_t a = ipbytes[0];
    uint32_t b =  ( uint32_t)ipbytes[1] << 8;
    uint32_t c =  ( uint32_t)ipbytes[2] << 16;
    uint32_t d =  ( uint32_t)ipbytes[3] << 24;
    return a+b+c+d;
}
  • I hope this helps. Enjoy !! – Chamberton Mata Mar 18 '16 at 07:25
  • You initialize an array to store your bytes all with zeros. You traverse the ip string and each digit you encounter is multiplied by 10 if there are still digits within the same block (in dotted notation) i.e before the dot (.) [This is equivalent to left shif (x2) in binary]. The rest of the code just applies the correct right shift to the integer value of each block. – Chamberton Mata Mar 18 '16 at 15:45
0

inet_pton() minimal runnable example

Mentioned at: https://stackoverflow.com/a/34077884/895245 but here's an example adapted from man inet_pton:

pton.c

#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
    struct in_addr addr;
    int s;

    if (argc != 2) {
        exit(EXIT_FAILURE);
    }
    s = inet_pton(AF_INET, argv[1], &addr);
    if (s <= 0) {
        if (s == 0)
            fprintf(stderr, "Not in presentation format");
        else
            perror("inet_pton");
        exit(EXIT_FAILURE);
    }
    printf("0x%08x\n", ntohl(addr.s_addr));
    exit(EXIT_SUCCESS);
}

Compile:

gcc -o pton.out pton.c

Run:

./pton.out 192.187.1.42

Output:

0xc0bb012a

So we see that the strings was converted to an integer, e.g.:

  • 0xc0 = 192
  • 0xbb = 187
  • 0x01 = 1
  • 0x2a = 42

Related quote of interest from man inet_pton comparing different options:

Unlike inet_aton(3) and inet_addr(3), inet_pton() supports IPv6 addresses. On the other hand, inet_pton() accepts only IPv4 addresses in dotted-decimal notation, whereas in‐ et_aton(3) and inet_addr(3) allow the more general numbers-and-dots notation (hexadecimal and octal number formats, and formats that don't require all four bytes to be explicitly written). For an interface that handles both IPv6 addresses, and IPv4 addresses in numbers-and-dots notation, see getaddrinfo(3).

Tested on Ubuntu 23.04.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985