Convert an ip address to long value

K

kyle.tk

I am trying to write a function to convert an ipv4 address that is held
in the string char *ip to its long value equivalent. Here is what I
have right now, but I can't seem to get it to work.

#include <string.h>
#include <stdio.h>

/* Convert an ipv4 address to long integer */
/* "192.168.1.1" --> 3232235777 */
unsigned long iptol(char *ip){
unsigned char o1,o2,o3,o4; /* The 4 ocets */
char tmp[13] = "000000000000\0";
short i = 11; /* Current Index in tmp */
short j = (strlen(ip) - 1);
do {
if ((ip[--j] == '.')){
i -= (i % 3);
}
else {
tmp[--i] = ip[j];
}
} while (i > -1);
o1 = (tmp[0] * 100) + (tmp[1] * 10) + tmp[2];
o2 = (tmp[3] * 100) + (tmp[4] * 10) + tmp[5];
o3 = (tmp[6] * 100) + (tmp[7] * 10) + tmp[8];
o4 = (tmp[9] * 100) + (tmp[10] * 10) + tmp[11];
return (o1 * 16777216) + (o2 * 65536) + (o3 * 256) + o4;
}

int main(void){
char *ip = "124.15.22.102";
iptol(ip);
}

Any suggestions? Maybe there is a better way to do this?

-kyle
 
M

Michael Mair

kyle.tk said:
I am trying to write a function to convert an ipv4 address that is held
in the string char *ip to its long value equivalent. Here is what I
have right now, but I can't seem to get it to work.

#include <string.h>
#include <stdio.h>

/* Convert an ipv4 address to long integer */
/* "192.168.1.1" --> 3232235777 */
unsigned long iptol(char *ip){
unsigned char o1,o2,o3,o4; /* The 4 ocets */
char tmp[13] = "000000000000\0";
short i = 11; /* Current Index in tmp */
short j = (strlen(ip) - 1);
do {
if ((ip[--j] == '.')){
i -= (i % 3);
}
else {
tmp[--i] = ip[j];
}
} while (i > -1);
o1 = (tmp[0] * 100) + (tmp[1] * 10) + tmp[2];
o2 = (tmp[3] * 100) + (tmp[4] * 10) + tmp[5];
o3 = (tmp[6] * 100) + (tmp[7] * 10) + tmp[8];
o4 = (tmp[9] * 100) + (tmp[10] * 10) + tmp[11];
return (o1 * 16777216) + (o2 * 65536) + (o3 * 256) + o4;
}

int main(void){
char *ip = "124.15.22.102";
iptol(ip);
}

Any suggestions? Maybe there is a better way to do this?

Too lazy to look right now; consider

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define NUM_OCTETTS 4

int iptoul (const char *ip, unsigned long *plong)
{
char *next = NULL;
const char *curr = ip;
unsigned long tmp;
int i, err = 0;

*plong = 0;
for (i = 0; i < NUM_OCTETTS; i++) {
tmp = strtoul(curr, &next, 10);
if (tmp >= 256
|| (tmp == 0 && next == curr))
{
err++;
break;
}
*plong = (*plong << 8) + tmp;
curr = next + 1;
}

if (err) {
return 1;
}
else {
return 0;
}
}

int main (void)
{
const char *ip = "124.15.22.102";
unsigned long ret;

if (0 == iptoul(ip, &ret))
printf("%s -> %lu\n", ip, ret);

return 0;
}

Cheers
Michael
 
M

Michael Mair

Michael said:
kyle.tk said:
I am trying to write a function to convert an ipv4 address that is held
in the string char *ip to its long value equivalent. Here is what I
have right now, but I can't seem to get it to work.

#include <string.h>
#include <stdio.h>

/* Convert an ipv4 address to long integer */
/* "192.168.1.1" --> 3232235777 */
unsigned long iptol(char *ip){
unsigned char o1,o2,o3,o4; /* The 4 ocets */
char tmp[13] = "000000000000\0";
short i = 11; /* Current Index in tmp */
short j = (strlen(ip) - 1);
do {
if ((ip[--j] == '.')){
i -= (i % 3);
}
else {
tmp[--i] = ip[j];
}
} while (i > -1);
o1 = (tmp[0] * 100) + (tmp[1] * 10) + tmp[2];
o2 = (tmp[3] * 100) + (tmp[4] * 10) + tmp[5];
o3 = (tmp[6] * 100) + (tmp[7] * 10) + tmp[8];
o4 = (tmp[9] * 100) + (tmp[10] * 10) + tmp[11];
return (o1 * 16777216) + (o2 * 65536) + (o3 * 256) + o4;
}

int main(void){
char *ip = "124.15.22.102";
iptol(ip);
}

Any suggestions? Maybe there is a better way to do this?


Too lazy to look right now; consider

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define NUM_OCTETTS 4

int iptoul (const char *ip, unsigned long *plong)
{
char *next = NULL;
const char *curr = ip;
unsigned long tmp;
int i, err = 0;

*plong = 0;
for (i = 0; i < NUM_OCTETTS; i++) {
tmp = strtoul(curr, &next, 10);
if (tmp >= 256
|| (tmp == 0 && next == curr))
{
err++;
break;
}
Forgot the obvious one:
if (*next != '.' && i != (NUM_OCTETTS-1)) {
err++;
break;
}
 
E

Eric Sosman

kyle.tk wrote On 01/31/06 15:27,:
I am trying to write a function to convert an ipv4 address that is held
in the string char *ip to its long value equivalent. Here is what I
have right now, but I can't seem to get it to work.

#include <string.h>
#include <stdio.h>

/* Convert an ipv4 address to long integer */
/* "192.168.1.1" --> 3232235777 */
unsigned long iptol(char *ip){
unsigned char o1,o2,o3,o4; /* The 4 ocets */
char tmp[13] = "000000000000\0";
short i = 11; /* Current Index in tmp */
short j = (strlen(ip) - 1);
do {
if ((ip[--j] == '.')){
i -= (i % 3);
}
else {
tmp[--i] = ip[j];
}
} while (i > -1);
o1 = (tmp[0] * 100) + (tmp[1] * 10) + tmp[2];
o2 = (tmp[3] * 100) + (tmp[4] * 10) + tmp[5];
o3 = (tmp[6] * 100) + (tmp[7] * 10) + tmp[8];
o4 = (tmp[9] * 100) + (tmp[10] * 10) + tmp[11];
return (o1 * 16777216) + (o2 * 65536) + (o3 * 256) + o4;
}

int main(void){
char *ip = "124.15.22.102";
iptol(ip);
}

Any suggestions? Maybe there is a better way to do this?

You could use sscanf(). Unfortunately, it's hard
to persuade sscanf() to reject things like "123.0.0.-1"
or " 127. 0. 0. 1".

Another possibility would be to use isdigit() to
check the first character of each field and then strtoul()
to convert it, then check that strtoul() stopped on a '.'
(or on a '\0' the final time). You might also check that
the stopping point wasn't too far from the start, so as
to reject "000000000000127.0.0.000000000000000001".
 
O

Old Wolf

kyle.tk said:
I am trying to write a function to convert an ipv4 address that is held
in the string char *ip to its long value equivalent. Here is what I
have right now, but I can't seem to get it to work.

#include <string.h>
#include <stdio.h>

/* Convert an ipv4 address to long integer */
/* "192.168.1.1" --> 3232235777 */
unsigned long iptol(char *ip){
unsigned char o1,o2,o3,o4; /* The 4 ocets */
char tmp[13] = "000000000000\0";

That \0 is not necessary.
short i = 11; /* Current Index in tmp */
short j = (strlen(ip) - 1);
do {
if ((ip[--j] == '.')){
i -= (i % 3);
}
else {
tmp[--i] = ip[j];
}
} while (i > -1);

Well, let's work through this loop.
Start: i = 11, j = 10.
Iter 1: j => 9. ip[9] == '.' so i => 9.
Iter 2: j => 8. i => 8. tmp[8] = ip[8] = '1'.
Iter 3: j => 7. ip[7] == '.' so i => 6.
Iter 4: j => 6. i => 5. tmp[5] = ip[6] = '8'.
Iter 5: j => 5. i => 4. tmp[4] = ip[5] = '6'.
Iter 6: j => 4. i => 3. tmp[3] = ip[4] = '1'.
Iter 7: j => 3. ip[3] = '.', so i => 3.
Iter 8: j => 2. i => 2. tmp[2] = ip[2] = '2'.
Iter 9: j => 1. i => 1. tmp[1] = ip[1] = '9'.
Iter10: j => 0. i => 0. tmp[0] = ip[0] = '1'.
Iter11: j => -1. Undefined behaviour, reading ip[-1].
Maybe will try and write to tmp[-1].

So you end up with tmp = "192168001000" and maybe having
written a buffer overflow before the start of tmp.

Hopefully it's now clear that your loop structure is pretty
weak and error-prone. A much better approach here is
to read forwards through ip, computing as you go, you
don't need to create a new array.
o1 = (tmp[0] * 100) + (tmp[1] * 10) + tmp[2];
o2 = (tmp[3] * 100) + (tmp[4] * 10) + tmp[5];
o3 = (tmp[6] * 100) + (tmp[7] * 10) + tmp[8];
o4 = (tmp[9] * 100) + (tmp[10] * 10) + tmp[11];

tmp[0] is '1'. '1' * 100 will probably give you a value of 4900.
You mean to write: (tmp[0] - '0') * 100 , etc.
 
K

kyle.tk

Michael said:
kyle.tk said:
I am trying to write a function to convert an ipv4 address that is held
in the string char *ip to its long value equivalent. Here is what I
have right now, but I can't seem to get it to work.

#include <string.h>
#include <stdio.h>

/* Convert an ipv4 address to long integer */
/* "192.168.1.1" --> 3232235777 */
unsigned long iptol(char *ip){
unsigned char o1,o2,o3,o4; /* The 4 ocets */
char tmp[13] = "000000000000\0";
short i = 11; /* Current Index in tmp */
short j = (strlen(ip) - 1);
do {
if ((ip[--j] == '.')){
i -= (i % 3);
}
else {
tmp[--i] = ip[j];
}
} while (i > -1);
o1 = (tmp[0] * 100) + (tmp[1] * 10) + tmp[2];
o2 = (tmp[3] * 100) + (tmp[4] * 10) + tmp[5];
o3 = (tmp[6] * 100) + (tmp[7] * 10) + tmp[8];
o4 = (tmp[9] * 100) + (tmp[10] * 10) + tmp[11];
return (o1 * 16777216) + (o2 * 65536) + (o3 * 256) + o4;
}

int main(void){
char *ip = "124.15.22.102";
iptol(ip);
}

Any suggestions? Maybe there is a better way to do this?

Too lazy to look right now; consider

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define NUM_OCTETTS 4

int iptoul (const char *ip, unsigned long *plong)
{
char *next = NULL;
const char *curr = ip;
unsigned long tmp;
int i, err = 0;

*plong = 0;
for (i = 0; i < NUM_OCTETTS; i++) {
tmp = strtoul(curr, &next, 10);
if (tmp >= 256
|| (tmp == 0 && next == curr))
{
err++;
break;
}
*plong = (*plong << 8) + tmp;
curr = next + 1;
}

if (err) {
return 1;
}
else {
return 0;
}
}

int main (void)
{
const char *ip = "124.15.22.102";
unsigned long ret;

if (0 == iptoul(ip, &ret))
printf("%s -> %lu\n", ip, ret);

return 0;
}

Cheers
Michael

Alright, after looking at that post I came up with this. I didn't use
yours verbatim because I have not yet implemented the stroul function.

Heres what I have got now. Critique?

unsigned long iptol(const char *ip){
unsigned long value = 0; /* Total Value */
unsigned char ocet = 0; /* Ocet Value */
int i = strlen(ip) - 1; /* Index in ip */
int m = 1; /* Ocet multiplier */
int j;
for (j=0; j < 4; j++){
while ( ip != '.' && ip != '\0' ){
ocet += m * (ip - 48);
m *= 10;
i--;
}
value += (ocet << (8 * j));
ocet = 0;
m = 1;
i--;
};
return value;
}


-kyle
 
R

Rod Pemberton

kyle.tk said:
I am trying to write a function to convert an ipv4 address that is held
in the string char *ip to its long value equivalent. Here is what I
have right now, but I can't seem to get it to work.

#include <string.h>
#include <stdio.h>

/* Convert an ipv4 address to long integer */
/* "192.168.1.1" --> 3232235777 */
unsigned long iptol(char *ip){
unsigned char o1,o2,o3,o4; /* The 4 ocets */
char tmp[13] = "000000000000\0";
short i = 11; /* Current Index in tmp */
short j = (strlen(ip) - 1);
do {
if ((ip[--j] == '.')){
i -= (i % 3);
}
else {
tmp[--i] = ip[j];
}
} while (i > -1);
o1 = (tmp[0] * 100) + (tmp[1] * 10) + tmp[2];
o2 = (tmp[3] * 100) + (tmp[4] * 10) + tmp[5];
o3 = (tmp[6] * 100) + (tmp[7] * 10) + tmp[8];
o4 = (tmp[9] * 100) + (tmp[10] * 10) + tmp[11];
return (o1 * 16777216) + (o2 * 65536) + (o3 * 256) + o4;
}

int main(void){
char *ip = "124.15.22.102";
iptol(ip);
}

Any suggestions? Maybe there is a better way to do this?

Yes, this is an alternate method, using more string processing. It compiles
and works for DJGPP and OW1.3:


#include <stdio.h>
#include <string.h>

unsigned long iptoul(char *ip)
{
char i,*tmp;
unsigned long val=0, cvt;

tmp=strtok(ip,".");
for (i=0;i<4;i++)
{
sscanf(tmp,"%lu",&cvt);
val<<=8;
val|=(unsigned char)cvt;
tmp=strtok(NULL,".");
}
return(val);
}

int main(void)
{

char *ip="124.15.22.102";

unsigned long ret;

printf("%s\n",ip);
ret=iptoul(ip);
printf("%08lx\n",ret);


return(0);
}


Rod Pemberton
 
W

websnarf

kyle.tk said:
I am trying to write a function to convert an ipv4 address that is held
in the string char *ip to its long value equivalent. Here is what I
have right now, but I can't seem to get it to work.

#include <string.h>
#include <stdio.h>

/* Convert an ipv4 address to long integer */
/* "192.168.1.1" --> 3232235777 */
unsigned long iptol(char *ip){
unsigned char o1,o2,o3,o4; /* The 4 ocets */
char tmp[13] = "000000000000\0";
short i = 11; /* Current Index in tmp */
short j = (strlen(ip) - 1);
do {
if ((ip[--j] == '.')){
i -= (i % 3);
}
else {
tmp[--i] = ip[j];
}
} while (i > -1);
o1 = (tmp[0] * 100) + (tmp[1] * 10) + tmp[2];
o2 = (tmp[3] * 100) + (tmp[4] * 10) + tmp[5];
o3 = (tmp[6] * 100) + (tmp[7] * 10) + tmp[8];
o4 = (tmp[9] * 100) + (tmp[10] * 10) + tmp[11];
return (o1 * 16777216) + (o2 * 65536) + (o3 * 256) + o4;
}

I don't see any any conversion from character to digits (via a "- '0'"
kind of operation.) So I can't see how this is possibly supposed to
work. Furthermore, it is possible and legal to specify IP addresses
in which each portion might exceed 255, and therefore might have more
than 3 digits -- its supposed to just wrap around.
int main(void){
char *ip = "124.15.22.102";
iptol(ip);
}

Any suggestions? Maybe there is a better way to do this?

This is off the top of my head:

unsigned long iptol (const char *ip) {
unsigned long ipl, b;
int i, m;
for (b = ipl = 0ul, m=4, i = 0; ; i++) {
switch (ip) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
b = b*10 + ip - '0';
break;
default:
ipl = (ipl << 8ul) + b;
if ('.' != ip || 0==(--m)) return ipl;
b = 0;
break;
}
}
}
 
C

CBFalconer

kyle.tk said:
.... snip ...

Alright, after looking at that post I came up with this. I didn't use
yours verbatim because I have not yet implemented the stroul function.

strtoul() is a standard function. You don't need to implement it.

--
"The power of the Executive to cast a man into prison without
formulating any charge known to the law, and particularly to
deny him the judgement of his peers, is in the highest degree
odious and is the foundation of all totalitarian government
whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
 
K

kyle.tk

CBFalconer said:
strtoul() is a standard function. You don't need to implement it.

I know it is a standard function in libc. The platform I am targeting
does not yet have a fully ported libc.

-kyle
 
P

Peter Nilsson

kyle.tk said:
Alright, after looking at that post I came up with this. I didn't use
yours verbatim because I have not yet implemented the stroul function.

You don't said:
Heres what I have got now. Critique?

unsigned long iptol(const char *ip){
unsigned long value = 0; /* Total Value */
unsigned char ocet = 0; /* Ocet Value */
int i = strlen(ip) - 1; /* Index in ip */

This can fail if ip points to an empty string. But you don't need to
read
the string from right to left.
int m = 1; /* Ocet multiplier */
int j;

These are really redundant if you read the string from left to right.
for (j=0; j < 4; j++){
while ( ip != '.' && ip != '\0' ){


Given where i started, you're not going to encounter a '\0', so that
test is
redundant.
ocet += m * (ip - 48);


'0' is more portable than a literal 48. You're condition test doesn't
check that
ip is a digit, only that it's not '.', so you're conversion here is
somewhat
wreckless, even with the '0' == 48 presumption.
m *= 10;
i--;
}
value += (ocet << (8 * j));
ocet = 0;
m = 1;
i--;
};
return value;
}

If you don't care about error cases...

unsigned long iptol2(const char *ip)
{
unsigned long ul = 0;
unsigned octet = 0;
for (; *ip; ip++)
{
if ('0' <= *ip && *ip <= '9')
octet = octet * 10 + (*ip - '0');
else if (*ip == '.')
{
ul = (ul << 8) + octet;
octet = 0;
}
}
return (ul << 8) + octet;
}
 
C

CBFalconer

Peter said:
.... snip code ...
.... snip code ...

If you don't care about error cases...

unsigned long iptol2(const char *ip)
{
unsigned long ul = 0;
unsigned octet = 0;
for (; *ip; ip++)
{
if ('0' <= *ip && *ip <= '9')
octet = octet * 10 + (*ip - '0');
else if (*ip == '.')
{
ul = (ul << 8) + octet;
octet = 0;
}
}
return (ul << 8) + octet;
}

Untested, but somewhat more robust IMO:

unsigned long iptoul(const char *ip) {
unsigned int octet;
int count;
unsigned long ul;

count = 0; ul = 0;
while (' ' == *ip) ip++; /* absorb leading blanks */
do {
octet = 0;
while (('0' <= *ip) && (*ip <= '9')) {
octet = 10 * octet + (*ip - '0');
ip++;
}
count++;
ul = 256 * ul + (count % 256);
if ('.' == *ip) *ip++;
} while ((count < NUM_OCTETS) &&
('0' <= *ip) && (*ip <= '9'));
return ul;
}

which also avoids std library calls, i.e. isdigit

--
"The power of the Executive to cast a man into prison without
formulating any charge known to the law, and particularly to
deny him the judgement of his peers, is in the highest degree
odious and is the foundation of all totalitarian government
whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
 
B

Barry

Eric Sosman said:
kyle.tk wrote On 01/31/06 15:27,:
I am trying to write a function to convert an ipv4 address that is held
in the string char *ip to its long value equivalent. Here is what I
have right now, but I can't seem to get it to work.

#include <string.h>
#include <stdio.h>

/* Convert an ipv4 address to long integer */
/* "192.168.1.1" --> 3232235777 */
unsigned long iptol(char *ip){
unsigned char o1,o2,o3,o4; /* The 4 ocets */
char tmp[13] = "000000000000\0";
short i = 11; /* Current Index in tmp */
short j = (strlen(ip) - 1);
do {
if ((ip[--j] == '.')){
i -= (i % 3);
}
else {
tmp[--i] = ip[j];
}
} while (i > -1);
o1 = (tmp[0] * 100) + (tmp[1] * 10) + tmp[2];
o2 = (tmp[3] * 100) + (tmp[4] * 10) + tmp[5];
o3 = (tmp[6] * 100) + (tmp[7] * 10) + tmp[8];
o4 = (tmp[9] * 100) + (tmp[10] * 10) + tmp[11];
return (o1 * 16777216) + (o2 * 65536) + (o3 * 256) + o4;
}

int main(void){
char *ip = "124.15.22.102";
iptol(ip);
}

Any suggestions? Maybe there is a better way to do this?

You could use sscanf(). Unfortunately, it's hard
to persuade sscanf() to reject things like "123.0.0.-1"
or " 127. 0. 0. 1".

Another possibility would be to use isdigit() to
check the first character of each field and then strtoul()
to convert it, then check that strtoul() stopped on a '.'
(or on a '\0' the final time). You might also check that
the stopping point wasn't too far from the start, so as
to reject "000000000000127.0.0.000000000000000001".

Actually sscanf() is a simple and very common method. The sscanf itself
doesn't necessarily need
to validate the address. So things like

if (sscanf(hostname, "%u.%u.%u.%u",
ip[0],ip[1], ip[2],ip[3]) == 4)
{
}

are a good start.
 
C

CBFalconer

Barry said:
.... snip ...

Actually sscanf() is a simple and very common method. The sscanf
itself doesn't necessarily need to validate the address. So things
like

if (sscanf(hostname, "%u.%u.%u.%u",
ip[0],ip[1], ip[2],ip[3]) == 4)
{
}

are a good start.
From responses elsethread it appears that the OP is on embedded
systems without a full library available. If he doesn't have
strtol he certainly doesn't have the much bigger scanf interpreter.

--
"The power of the Executive to cast a man into prison without
formulating any charge known to the law, and particularly to
deny him the judgement of his peers, is in the highest degree
odious and is the foundation of all totalitarian government
whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
 
J

Jirka Klaue

CBFalconer:
Untested, but somewhat more robust IMO:

Maybe you should have tested it.
unsigned long iptoul(const char *ip) {
unsigned int octet;
int count;
unsigned long ul;

count = 0; ul = 0;
while (' ' == *ip) ip++; /* absorb leading blanks */
do {
octet = 0;
while (('0' <= *ip) && (*ip <= '9')) {
octet = 10 * octet + (*ip - '0');
ip++;
}
count++;
ul = 256 * ul + (count % 256);

"count" should be spelled "octet".
if ('.' == *ip) *ip++;

The second * is superfluous.
} while ((count < NUM_OCTETS) &&
('0' <= *ip) && (*ip <= '9'));
return ul;
}

which also avoids std library calls, i.e. isdigit

Additionally, the function returns 1.2.3.4 for any valid IP-address.
Very robust indeed. :)

Jirka
 
C

Chris Torek

This is a bit off-topic but...

tmp = strtoul(curr, &next, 10);

(... which handles each of the four parts of a "10.9.8.7" style IPv4
address.)

Traditionally, each octet is allowed to be in decimal, hex, or
octal, independent of each previous octet. To match "traditional
BSD semantics", make the strtoul() call above use base 0.

Yes, this means that you can "ping 192.0xb2.031.249". No, there
is no particularly good reason to do that -- and some implementations
do not allow it (but some spammers do depend on it to hide their
"real" IP addresses).

(Traditional BSD libraries also allow the entire 32-bit address to
be given as a single number, but that requires more code, whereas
changing the last argument to strtoul() does not.)
 
M

Michael Mair

Chris said:
This is a bit off-topic but...



(... which handles each of the four parts of a "10.9.8.7" style IPv4
address.)

Traditionally, each octet is allowed to be in decimal, hex, or
octal, independent of each previous octet. To match "traditional
BSD semantics", make the strtoul() call above use base 0.

Yes, this means that you can "ping 192.0xb2.031.249". No, there
is no particularly good reason to do that -- and some implementations
do not allow it (but some spammers do depend on it to hide their
"real" IP addresses).

(Traditional BSD libraries also allow the entire 32-bit address to
be given as a single number, but that requires more code, whereas
changing the last argument to strtoul() does not.)

Thank you -- I was not aware of this bit of "evolved" semantics ;-)

Cheers
Michael
 
C

CBFalconer

Jirka said:
CBFalconer:


Maybe you should have tested it.


"count" should be spelled "octet".


The second * is superfluous.


Additionally, the function returns 1.2.3.4 for any valid IP-address.
Very robust indeed. :)

Which proves I should have tested it, instead of being impressed by
my own infallibility at the keyboard :) However I suspect it will
work correctly after the repairs you have pointed out (still not
tested), and will do respectable and controlled things with faulty
input and unusual systems. Which was my objective.

Thank you for the corrections. At least it was sufficiently
legible for others to follow my peculiar warped logic.

--
"The power of the Executive to cast a man into prison without
formulating any charge known to the law, and particularly to
deny him the judgement of his peers, is in the highest degree
odious and is the foundation of all totalitarian government
whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
 
R

RSoIsCaIrLiIoA

I am trying to write a function to convert an ipv4 address that is held
in the string char *ip to its long value equivalent. Here is what I
have right now, but I can't seem to get it to work.

this is an assembly 'solution' with the use of C library functions
i think it could be easyly ported to linux-gcc, windows-[c-compiler]
but has the need of >= intel 386 cpu

; nasmw -f obj this_file.asm
; bcc32 this_file.obj

section _DATA public align=4 class=DATA use32

Scrivi_numero_ip db "Srivi un internet adr. > " , 0
Errore db "Errore" , 10 , 0
Errore1 db "Errore" , 0
Errore_linea_troppo_lunga db "Errore linea troppo lunga" , 0
Numero_naturale_conversione_$u
db "Numero naturale conversione %u" , 10 , 0
Errore_contenuto_linea db "Errore contenuto linea" , 10 , 0

$lf db "%lf" , 0
errno_u_$i db "errno=%i " , 0
$u_$u db " <%u %u> " , 0
$i_p$i_p$i_p$i db " %d.%d.%d.%d%*[^" , 10 , "]" , 0
val db 0

extern _printf , _errno , _sscanf , _fgets
extern _perror , __streams
global _main

section _TEXT public align=1 class=CODE use32

; ip_to_ul(dword* ris, dword* arr)
; k=0k, 4Ra, 8ris, 12arr
ip_to_ul:
push ebp
mov ebp, esp ; p1[4], p2[4], p3[4], p4[4]
sub esp, 32 ; 5..8, 9..12, 13..16, 17..20<32
push ebx
push ecx
push edx
push esi
push edi
%define @ris ebp+8
%define @arr ebp+12
%define @p1 ebp-8
%define @p2 ebp-12
%define @p3 ebp-16
%define @p4 ebp-20
mov esi, [@arr]
lea eax, [@p1]
lea ebx, [@p2]
lea ecx, [@p3]
lea edx, [@p4]
push edx
push ecx
push ebx
push eax
push $i_p$i_p$i_p$i
push esi
call _sscanf
add esp, 24
cmp eax, 4
je .a1
..a0:
mov eax, [@ris]
mov dword[eax], 0
jmp .fn
..a1:
cmp dword[@p1], 0
jl .a0
cmp dword[@p2], 0
jl .a0
cmp dword[@p3], 0
jl .a0
cmp dword[@p4], 0
jl .a0
cmp dword[@p1], 256
jg .a0
cmp dword[@p2], 256
jg .a0
cmp dword[@p3], 256
jg .a0
cmp dword[@p4], 256
jg .a0
mov eax, dword[@p1]
shl eax, 8
add eax, dword[@p2]
shl eax, 8
add eax, dword[@p3]
shl eax, 8
add eax, dword[@p4]
mov ebx, [@ris]
mov dword[ebx], 1
..fn:
%undef @ris
%undef @arr
%undef @p1
%undef @p2
%undef @p3
%undef @p4
pop edi
pop esi
pop edx
pop ecx
pop ebx
mov esp, ebp
pop ebp
ret


; k= 0k, 4Ra, 8@argc, 12@argv
_main: ; foo[256], sp[4], w[4]
push ebp ; 11..266, 267..270, 271..274<512
mov ebp, esp
sub esp, 512
push ebx
push esi
push edi
%define @argc ebp+8
%define @argv ebp+12
%define @foo ebp-266
%define @w ebp-274
mov eax, 0
mov ebx, ebp
..l0:
mov byte[ebx], 0
inc eax
dec ebx
cmp eax, 400
jb .l0
..a0:
push Scrivi_numero_ip
call _printf
add esp, 4
lea eax, [@foo]
push __streams ; it should be stdout
push 256
push eax
call _fgets
add esp, 12
cmp eax, 0
jne .l4
..l1:
push Errore
call _printf
add esp, 4
jmp .fine
..l2:
push Errore_linea_troppo_lunga
call _printf
add esp, 4
jmp .fine
..l3:
push Errore_contenuto_linea
call _printf
add esp, 4
jmp .fine
..l4:
cmp byte[eax+254], 0
jne .l2
lea ebx, [@w]
push eax
push ebx
call ip_to_ul
add esp, 8
cmp dword[@w], 0
je .l3
cmp eax, 0
je .fine
push eax
push Numero_naturale_conversione_$u
call _printf
add esp, 8
jmp .l0
..fine:
mov eax, 0
%undef @argc
%undef @argv
%undef @foo
%undef @w
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret
 
R

RSoIsCaIrLiIoA

I am trying to write a function to convert an ipv4 address that is held
in the string char *ip to its long value equivalent. Here is what I
have right now, but I can't seem to get it to work.

this is an assembly 'solution' with the use of C library functions
i think it could be easyly ported to linux-gcc, windows-[c-compiler]
but has the need of >= intel 386 cpu

; nasmw -f obj this_file.asm
; bcc32 this_file.obj

section _DATA public align=4 class=DATA use32

Scrivi_numero_ip db "Srivi un internet adr. > " , 0
Errore db "Errore" , 10 , 0
Errore1 db "Errore" , 0
Errore_linea_troppo_lunga db "Errore linea troppo lunga" , 0
Numero_naturale_conversione_$u
db "Numero naturale conversione %u" , 10 , 0
Errore_contenuto_linea db "Errore contenuto linea" , 10 , 0

$lf db "%lf" , 0
errno_u_$i db "errno=%i " , 0
$u_$u db " <%u %u> " , 0
$i_p$i_p$i_p$i db " %d.%d.%d.%d%*[^" , 10 , "]" , 0
val db 0

extern _printf , _errno , _sscanf , _fgets
extern _perror , __streams
global _main

section _TEXT public align=1 class=CODE use32

; ip_to_ul(dword* ris, dword* arr)
; k=0k, 4Ra, 8ris, 12arr
ip_to_ul:
push ebp
mov ebp, esp ; p1[4], p2[4], p3[4], p4[4]
sub esp, 32 ; 5..8, 9..12, 13..16, 17..20<32
push ebx
push ecx
push edx
push esi
push edi
%define @ris ebp+8
%define @arr ebp+12
%define @p1 ebp-8
%define @p2 ebp-12
%define @p3 ebp-16
%define @p4 ebp-20
mov esi, [@arr]
lea eax, [@p1]
lea ebx, [@p2]
lea ecx, [@p3]
lea edx, [@p4]
push edx
push ecx
push ebx
push eax
push $i_p$i_p$i_p$i
push esi
call _sscanf
add esp, 24
cmp eax, 4
je .a1
..a0:
mov eax, [@ris]
mov dword[eax], 0
jmp .fn
..a1:
cmp dword[@p1], 0
jl .a0
cmp dword[@p2], 0
jl .a0
cmp dword[@p3], 0
jl .a0
cmp dword[@p4], 0
jl .a0
cmp dword[@p1], 256
jg .a0
cmp dword[@p2], 256
jg .a0
cmp dword[@p3], 256
jg .a0
cmp dword[@p4], 256
jg .a0
mov eax, dword[@p1]
shl eax, 8
add eax, dword[@p2]
shl eax, 8
add eax, dword[@p3]
shl eax, 8
add eax, dword[@p4]
mov ebx, [@ris]
mov dword[ebx], 1
..fn:
%undef @ris
%undef @arr
%undef @p1
%undef @p2
%undef @p3
%undef @p4
pop edi
pop esi
pop edx
pop ecx
pop ebx
mov esp, ebp
pop ebp
ret


; k= 0k, 4Ra, 8@argc, 12@argv
_main: ; foo[256], sp[4], w[4]
push ebp ; 11..266, 267..270, 271..274<512
mov ebp, esp
sub esp, 512
push ebx
push esi
push edi
%define @argc ebp+8
%define @argv ebp+12
%define @foo ebp-266
%define @w ebp-274
mov eax, 0
mov ebx, ebp
..l0:
mov byte[ebx], 0
inc eax
dec ebx
cmp eax, 400
jb .l0
..a0:
push Scrivi_numero_ip
call _printf
add esp, 4
lea eax, [@foo]
push __streams ; it should be stdout
push 256
push eax
call _fgets
add esp, 12
cmp eax, 0
jne .l4
..l1:
push Errore
call _printf
add esp, 4
jmp .fine
..l2:
push Errore_linea_troppo_lunga
call _printf
add esp, 4
jmp .fine
..l3:
push Errore_contenuto_linea
call _printf
add esp, 4
jmp .fine
..l4:
cmp byte[eax+254], 0
jne .l2
lea ebx, [@w]
push eax
push ebx
call ip_to_ul
add esp, 8
cmp dword[@w], 0
je .l3
cmp eax, 0
je .fine
push eax
push Numero_naturale_conversione_$u
call _printf
add esp, 8
jmp .l0
..fine:
mov eax, 0
%undef @argc
%undef @argv
%undef @foo
%undef @w
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top