470,827 Members | 1,724 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,827 developers. It's quick & easy.

Help for a simple program!

Hi friends,

I am writing a simple program to convert an IP address from a
hexadecimal form to dotted-notation form. However, for some reason I am
having problem getting it to work.Here it is:

/* print an ip address, given a hexadecimal number in host byte order
*/
char *get_ip (unsigned int *number)
{
u_int8_t ip1, ip2, ip3, ip4, ip5, ip6;

char *address;
ip1 = (u_int8_t) (*number );
ip2 = (u_int8_t) (*( number + 1 ));
ip3 = (u_int8_t) (*( number + 2 ));
ip4 = (u_int8_t) (*( number + 3 ));

/*change the order of ip1, ip2, etc. because the host is a
little-endian machine */

asprintf(&address, "%u . %u . %u . %u", ip4, ip3, ip2, ip1);

return address;
}
int main()
{
unsigned int temp =0xD8736CF5; /* equivalent to 3631443187 or
216.115.108.245 */

printf("\n %s \n", get_ip(&temp));

return 0;
}
Somehow, when I run this code, I always get the last quartet right
(i.e. 245, which is also the first byte in a little endian machine);
but the remaining bytes are incorrect, and vary on different runs. A
few results I have gotten are: 1.154.168.245, 1.194.188.245,
1.244.198.245.

I tried it for different IP addresses. Always I get the last byte ( of
IP address) right, but the remaining are incorrect.

I suppose I am missing something very simple, but I cannot find it. Can
anybody help please?

Thanks!

Apr 9 '06 #1
5 2070
Btw, I ran this program on
* gcc version 2.95.4 20020320 [FreeBSD]
* gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-53)
and
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-54)

All three machines had an Intel CPU.

Apr 9 '06 #2
aw************@gmail.com wrote:
Hi friends,

I am writing a simple program to convert an IP address from a
hexadecimal form to dotted-notation form. However, for some reason I am
having problem getting it to work.Here it is:

/* print an ip address, given a hexadecimal number in host byte order
*/
char *get_ip (unsigned int *number)
{
u_int8_t ip1, ip2, ip3, ip4, ip5, ip6;
prefer standard types, ie. uint8_t.
char *address;
You don't assign anything to address!
ip1 = (u_int8_t) (*number );
ip2 = (u_int8_t) (*( number + 1 ));
ip3 = (u_int8_t) (*( number + 2 ));
ip4 = (u_int8_t) (*( number + 3 ));
number is a pointer to unsigned int, so adding one to it adds
sizeof(unsigned int), which isn't what you intended. try

const uint8_t* p = (uint8_t*)number;

then use p rather than number.

This isn't portable on a big-endian machine, you are better off using
shifts.
/*change the order of ip1, ip2, etc. because the host is a
little-endian machine */

asprintf(&address, "%u . %u . %u . %u", ip4, ip3, ip2, ip1);
What's asprintf?
return address;
}
int main()
{
unsigned int temp =0xD8736CF5; /* equivalent to 3631443187 or
216.115.108.245 */

printf("\n %s \n", get_ip(&temp));

return 0;
}
Somehow, when I run this code, I always get the last quartet right
(i.e. 245, which is also the first byte in a little endian machine);
but the remaining bytes are incorrect, and vary on different runs. A
few results I have gotten are: 1.154.168.245, 1.194.188.245,
1.244.198.245.

You must have ignored quite a few compiler warnings and I'm surprised it
even ran...

--
Ian Collins.
Apr 9 '06 #3
Hey Ian

thanks for pointing out the error. (which was incrementing pointer to
unsigned int rather than in single byte steps).. I don't know how could
have I made this error.. maybe an after-effect of programming beyond 3
am?

Ian Collins wrote:
You don't assign anything to address!


Yes. Please see explanation on asprintf below.

ip1 = (u_int8_t) (*number );
ip2 = (u_int8_t) (*( number + 1 ));
ip3 = (u_int8_t) (*( number + 2 ));
ip4 = (u_int8_t) (*( number + 3 ));

number is a pointer to unsigned int, so adding one to it adds
sizeof(unsigned int), which isn't what you intended. try

const uint8_t* p = (uint8_t*)number;

then use p rather than number.


worked like a charm. thanks again!

This isn't portable on a big-endian machine, you are better off using
shifts.
Could you explain this a little more?

asprintf(&address, "%u . %u . %u . %u", ip4, ip3, ip2, ip1);

What's asprintf?


asprintf is just like sprintf .. it assigns the output of printf to a
char pointer; except that it allocates memory dynamically.. so it is
safer than sprintf.


You must have ignored quite a few compiler warnings and I'm surprised it
even ran...


looks like my compiler suppresses the warnings by default.

Thanks so much!

Ashish

Apr 9 '06 #4
aw************@gmail.com wrote:
Hey Ian

thanks for pointing out the error. (which was incrementing pointer to
unsigned int rather than in single byte steps).. I don't know how could
have I made this error.. maybe an after-effect of programming beyond 3
am?
Never a good idea!
Ian Collins wrote:
You don't assign anything to address!

Yes. Please see explanation on asprintf below.

ip1 = (u_int8_t) (*number );
ip2 = (u_int8_t) (*( number + 1 ));
ip3 = (u_int8_t) (*( number + 2 ));
ip4 = (u_int8_t) (*( number + 3 ));


number is a pointer to unsigned int, so adding one to it adds
sizeof(unsigned int), which isn't what you intended. try

const uint8_t* p = (uint8_t*)number;

then use p rather than number.

worked like a charm. thanks again!

This isn't portable on a big-endian machine, you are better off using
shifts.

Could you explain this a little more?

Run your program on a big endian machine and the result will be
245.108.115.216 due to the byte order being reversed.

Try

ip4 = (*number >> 24)&0xff;
ip3 = (*number >> 16)&0xff;
ip2 = (*number >> 8)&0xff;
ip1 = (*number)&0xff;

Which gives the expected result on either.

By the way, why pass number as a pointer?
asprintf(&address, "%u . %u . %u . %u", ip4, ip3, ip2, ip1);


What's asprintf?

asprintf is just like sprintf .. it assigns the output of printf to a
char pointer; except that it allocates memory dynamically.. so it is
safer than sprintf.

OK, it's just non-standard.

--
Ian Collins.
Apr 9 '06 #5
ed
On Sun, 09 Apr 2006 20:23:40 +1200
Ian Collins <ia******@hotmail.com> wrote:
asprintf(&address, "%u . %u . %u . %u", ip4, ip3, ip2,
ip1);

What's asprintf?


As awasthi says, it's non-standard, for completeness here's the man page
snippet:

NAME
asprintf, vasprintf - print to allocated string

SYNOPSIS
#define _GNU_SOURCE
#include <stdio.h>

int asprintf(char **strp, const char *fmt, ...);

int vasprintf(char **strp, const char *fmt, va_list ap);

DESCRIPTION
The functions asprintf and vasprintf are analogues of sprintf and
vsprintf, except that they allocate a string large enough to hold the
output including the terminating NUL, and return a pointer to it via the
first parameter. This pointer should be passed to free(3) to release the
allocated storage when it is no longer needed.

RETURN VALUE
When successful, these functions return the number of bytes
printed, just like sprintf(3). If memory allocation wasn't possible, or
some other error occurs, these functions will return -1, and the
contents of strp is undefined.

NOTES
These functions are GNU extensions, not in C or POSIX. They are
also available under *BSD. The FreeBSD implementation sets strp to
NULL on error.

For portability this could be done in a few lines of ones own functions.

--
Regards, Ed :: http://www.s5h.net
:%s/\t/ /g :: proud unix system person
:%s/Open Source/Free Software/g
Apr 9 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

31 posts views Thread by da Vinci | last post: by
10 posts views Thread by atlanta | last post: by
2 posts views Thread by Vitali Gontsharuk | last post: by
8 posts views Thread by pamelafluente | last post: by
6 posts views Thread by toch3 | last post: by
5 posts views Thread by dav3 | last post: by
reply views Thread by mihailmihai484 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.