I am trying to convert ip values as hex contained in uint32_t
data type. So I dont think this is any wrong since inet_ntoa gets iphdr->saddr and iphdr->daddr
but I get segFault at inet_ntoa function call. gcc warning says
warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
92 | char *recv = inet_ntoa(*(struct in_addr*)
this is my code
uint32_t temp =getlastbyte();
uint32_t *x=(void *)(0xc0a80a02&temp);
char *recv = inet_ntoa(*(struct in_addr*)
*x);
and when I removed this cast *(struct in_addr*)
then my code does not compile
any solution to this. please tell
error
^
code.c:93:26: error: incompatible type for argument 1 of ‘inet_ntoa’
93 | *x);
| ^~
| |
| uint32_t {aka unsigned int}
CodePudding user response:
The prototype for inet_ntoa is char* inet_ntoa( struct in_addr in )
, with in_addr essentially being defined as struct in_addr { uint32_t s_addr; }
. inet_ntoa converts a network byte order (NBO) IPv4 address to a zero-terminated, dotted-decimal string. As such, one sets s_addr to a 32-bit IPv4 in NBO and passes that the containing in_addr object to inet_ntoa.
In reference to:
1 uint32_t temp =getlastbyte();
2 uint32_t *x=(void *)(0xc0a80a02&temp);
3 char *recv = inet_ntoa(*(struct in_addr*)*x);
There would seem to be several issues:
- Your second line would seem to be attempting to bitwise-and the 32-bit network byte order (NBO) representation of 192.168.10.2 with the return from
getlastbyte()
. I'm not sure why you'd want to do this; though, if you're trying to add a network address (e.g., 192.168.10.x) to a host address (e.g., x.x.x.50) to obtain the 32-bit NBO representation of something along the lines of 192.168.10.50, you'd want to bitwise-or (or add) (e.g.,0xC0A80A00 getlastbyte()
). - Your second line takes the value
0xC0A80A02 & temp
and attempts to cast it to a(void*)
, as if it were a valid memory address. Alternatively, you might want something along the lines ofuint32_t temp = 0xC0A80A00 getlastbyte(); uint32_t *x = &temp;
, which stores0xC0A80A00 getlastbyte()
intotemp
and then obtains a reference totemp
, storing that address in the pointerx
. In short, your second line is establishing a pointer to an invalid address, which is why, when being dereferenced in line 3, a SIGSEGV (segmentation fault) is triggered. - Your third line is attempting to dereference your invalid pointer and then dereference that. Continuing the speculated example from the previous bullet, perhaps you might want something along the lines of
char *recv = inet_ntoa(*(struct in_addr*)&temp)
orchar *recv = inet_ntoa(*(struct in_addr*)x)
. In short, you generally shouldn't attempt to cast a value to an address or vice versa, unless you truly mean to do so. - Your example doesn't seem to adequately consider byte-order; i.e., no host-to-network order conversions (e.g., using
htonl
). - It's generally ill-advised to assume bitwise equivalency for non-structured and structured types. Otherwise, compile-time data structure alignment issues may present.
In summary, I believe you may want something along the lines of (assuming you're truly trying to add 192.168.10.0 to a last octet or the like):
1 uint32_t ipn = htonl( 0xC0A80A00 getlastbyte() );
2 char *ipa = inet_ntoa(*(struct in_addr*)&ipn);
As a simple example to add the network address 192.168.10.0 to a .20 host address (compiled with gcc -Wall -o inet_ntoa inet_ntoa.c
and executed as ./inet_ntoa
on a Linux x86_64 host):
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/socket.h>
int main()
{
uint32_t ip = htonl( 0xC0A80A00 0x14 );
printf("%s\n",inet_ntoa(*(struct in_addr*)&ip));
return(0);
}
When run, this program produces the output:
192.168.10.20