I'm learning socket programming and am confused by what I feel is inconsistent use of htons() and family of functions in my learning material. I'm currently reading this site which has the following code segment:
001 1: struct sockaddr_in adr_inet;
002 2: int adr_len;
003 3:
004 4: memset(&adr_inet,0,sizeof adr_inet);
005 5:
006 6: adr_inet.sin_family = AF_INET;
007 7: adr_inet.sin_port = ntohs(0);
008 8: adr_inet.sin_addr.s_addr = ntohl(INADDR_ANY);
009 9: adr_len = sizeof adr_inet;
A subsequent example further down at the same noted site has the following code segment:
030 30: struct sockaddr_in adr_inet;/* AF_INET */
...
042 42: /* Create an AF_INET address */
043 43: memset(&adr_inet,0,sizeof adr_inet);
044 44:
045 45: adr_inet.sin_family = AF_INET;
046 46: adr_inet.sin_port = htons(9000);
047 47: memcpy(&adr_inet.sin_addr.s_addr,IPno,4);
048 48: len_inet = sizeof adr_inet;
049 49:
050 50: /* Now bind the address to the socket */
051 51: z = bind(sck_inet,
052 52: (struct sockaddr *)&adr_inet,
053 53: len_inet);
Question:
Why is ntohs() used on adr_inet.sin_port in the first instance, but htons() in the second?
Question:
Why is neither ntohs() nor htons() used on adr_inet.sin_family?
The noted site doesn't explain why ntohs() or htons() are used in their respective examples; it only says to "note the use of" said functions.
I understand endianness and that network byte order is big-endian order. My questions is more about when do you want a struct sockaddr_in's members in network vs. host byte order? In the second code example, .sin_port is set to network byte order before being passed to bind(). I can see the case for passing data to this function in either network or host byte order: bind() is a "network-related" function, so maybe it needs its data in network byte order; on the other hand bind() is executed on the host, so why shouldn't accept data in host byte order?
Why is ntohs() used on adr_inet.sin_port in the first instance, but htons() in the second?
The first is a mistake, but in practice works anyway.
Nowadays practically all machines use 8-bit bytes and either consistent big-endian or consistent little-endian formats. On the former both hton[sl] and ntoh[sl] are no-ops; on the latter both reverse the byte order, and thus actually do the same thing even though their intended semantics are different. Thus using the wrong one still works on all systems you're likely to run a program on.
Back when the socket API was designed this wasn't always the case; for example the then-popular PDP-11 somewhat infamously used 'middle-endian' (!) aka 'NUXI' order for 32-bit.
Why is neither ntohs() nor htons() used on adr_inet.sin_family?
Again in ancient times the Internet Protocol stack was only one of several (up to a dozen or so) competing network technologies. The family field distinguishes different types of sockaddr_* structures for these different protocols, which did not all follow the Internet 'rule' for big-endian, at least not consistently. As there was no universal network representation for family they just left it in host order -- which is usually more convenient for host software.
Nowadays in practice nobody uses any families but INET, INET6, and sometimes UNIX -- and the latter can be replaced by using named pipes in the filesystem which is usually at least as good.
Why is neither ntohs() nor htons() used on adr_inet.sin_family?
adr_inet.sin_family is initialized to the value of AF_INET. This is defined in bits/socket.h (which is called by netinet/in.h in your example) as:
#define PF_INET 2 /* IP protocol family. */
and then,
#define AF_INET PF_INET
So AF_INET is just a way for the program to identify the associated socket as a TCP/IP connection. It won't actually hold the value of an IPv4 address itself, so there's no need to perform an endian conversion on it.
Also, note that in newer iterations of C, netinet/in.h has a comment that states the following:
/* Functions to convert between host and network byte order.
Please note that these functions normally take `unsigned long int' or
`unsigned short int' values as arguments and also return them. But
this was a short-sighted decision since on different systems the types
may have different representations but the values are always the same. */
extern uint32_t ntohl (uint32_t __netlong) __THROW __attribute__ ((__const__));
extern uint16_t ntohs (uint16_t __netshort)
__THROW __attribute__ ((__const__));
extern uint32_t htonl (uint32_t __hostlong)
__THROW __attribute__ ((__const__));
extern uint16_t htons (uint16_t __hostshort)
__THROW __attribute__ ((__const__));
Whereas the website you're referencing cites the older use of unsigned long and unsigned short
datatypes for the conversion functions. So there's a chance you may encounter issues running code from that site if
you're using a newer version of C.
Related
So I am trying to use this built-in UART function (from the Vitis SDK from Xilinix) to determine if there is a valid byte to read over UART. I created this function to return 1 if there was a byte to read or 0 if there wasn't
u32 UartHasMessage(void){
if(XUartPs_IsReceiveData(&XUartPs_Main)){
return 1;
}
else{
return 0;
}
}
However, even when there is a byte to read over UART, this function always returns false.
The weird behavior I am experiencing is when I step through the code using the debugger, I call UartHasMessage() to check if there is a byte to read, and it returns false, but in the next line I call a function to read a byte over UART and that contains the correct byte I sent over the host.
u32 test - UartHasMessage();
UartGetByte(&HostReply);
How come this UartHasMessage always returns false, but then in the next line I am able to read the byte correctly?
Caveat: Without some more information, this is a bit speculative and might be a comment, but it is too large for that.
The information below comes from the Xilinx documentation on various pages ...
XUartPs_RecvByte will block until a byte is ready. So, no need to call XUartPs_IsReceiveData directly (I think that XUartPS_RecvByte calls it internally).
A web search on XUartPs_Main came up with nothing, so we'd need to see the definition you have.
Most Xilinx documentation uses UART_BASEADDRESS:
#define UART_BASEADDR XPAR_XUARTPS_0_BASEADDR
I found a definition:
#define XPAR_XUARTPS_0_BASEADDR 0xE0001000
You might be better off using a more standard method, such as calling the XUartPs_LookupConfig function to get the configuration table entry which has all relevant values.
I'm guessing that you created the XUartPS_Main definition.
But, based on what you posted, (needing &XUartPS_Main instead of XUartPS_Main), it is linked/loaded at the exact address of the UART register bank. Let's assume that address is (e.g.) 0x10000. So, we might have:
u32 XUartPS_Main __attribute__(at(0x10000));
The at is an extension that some build systems support (e.g. arm) that forces the variable to be loaded at a given address. So, let's assume we have that (even if the mechanism is slightly different (e.g.):
__attribute__((section(".ARM.__at_0x10000")))
The definition of XUARTPS_SR_OFFSET is:
#define XUARTPS_SR_OFFSET 0x002CU
Offsets are [typically] byte offsets.
Given:
#define XUartPs_IsReceiveData(BaseAddress) \
!((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \
(u32)XUARTPS_SR_RXEMPTY) == (u32)XUARTPS_SR_RXEMPTY)
Now if the definition of XUartPS_Main uses u32 [as above], we may have a problem because XUARTPS_SR_OFFSET will be treated as a u32 index and not a byte offset. So, it will access the wrong address.
So, try:
XUartPs_IsReceiveData((unsigned char *) &XUartPs_Main)
But, if it were me, I'd rework things to use Xilinx's standard definitions.
UPDATE:
Hi so XUartPs_main is defined as static XUartPs XUartPs_Main; I use it in a variety of functions such as a function to send bytes over uart and I call it by its address like I did with this function, all my other functions work as expected except this one. Is it possible it is something to do with the way the fifo works? –
29belgrade29
No, not all the API functions are the same.
The struct definition is [I synthesized this from the API doc]:
typedef struct {
u16 DeviceId; // Unique ID of device.
u32 BaseAddress; // Base address of device (IPIF)
u32 InputClockHz;
} XUartPs;
Somewhere in your code you had to initialize this with:
XUartPs_Main = XUartPs_ConfigTable[my_device_id];
Or, with:
XUartPs_Main = *XUartPs_LookupConfig(my_device_id);
If an API function is defined as (e.g.):
void api_dosomething(XUartPs_Config *cfg,...)
Then, you call it with:
api_dosomething(&XUartPs_Main,...);
So, most functions probably take such a pointer.
But, XUartPs_IsReceiveData does not want a pointer to a XUartPs_Config struct. It wants a base address. This is:
XUartPs_Main.BaseAddress
So, you want:
XUartPs_IsReceiveData(XUartPs_Main.BaseAddress)
I want to check the Ethernet header of packet that is porececed by iptables (1.4), so i need to write a module that catch packet and apply my function. I am looking for the mac destination value in the Ethernet header (just for test purpose), so the code should be like this:
static bool match(const struct sk_buff *skb, struct xt_action_param *par)
{
struct ethhdr *hdr;
hdr = eth_hdr(skb);
printk(KERN_INFO "hdr->h_dest 0x%x\n", hdr->h_dest);
printk(KERN_INFO "MACPROTO=%04x\n", hdr->h_proto);
The problem is that i cant get the correct value, i have some thing that is not even in the real frame (i checked that with Wireshark), so is it the right function to get Ethernet header attributs?
update:
i used the solution presented in the post, but still have wrong output, it's like if the structure point to wrong place
This image show result when i use nc to send "aaa" string, the ethernet header should be the same in the to frame, but as present in the result, it's not.
struct ethhdr is defined as such:
/*
* This is an Ethernet frame header.
*/
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
__be16 h_proto; /* packet type ID field */
} __attribute__((packed));
But your code is trying to print that byte array using %x:
printk(KERN_INFO "hdr->h_dest 0x%x\n", hdr->h_dest);
That makes no sense, and probably causes a compiler warning to be generated. This is kernel code - you are using -Werror and -Wall, right?
Good news: printk supports printing MAC addresses directly. From documentation/printk-formats.txt:
MAC/FDDI addresses:
%pM 00:01:02:03:04:05
%pMR 05:04:03:02:01:00
%pMF 00-01-02-03-04-05
%pm 000102030405
%pmR 050403020100
For printing 6-byte MAC/FDDI addresses in hex notation. The 'M' and 'm'
specifiers result in a printed address with ('M') or without ('m') byte
separators. The default byte separator is the colon (':').
Where FDDI addresses are concerned the 'F' specifier can be used after
the 'M' specifier to use dash ('-') separators instead of the default
separator.
For Bluetooth addresses the 'R' specifier shall be used after the 'M'
specifier to use reversed byte order suitable for visual interpretation
of Bluetooth addresses which are in the little endian order.
Passed by reference.
So you can just use this:
printk(KERN_INFO "hdr->h_dest 0x%pM\n", hdr->h_dest);
These format specifiers are provided anywhere vsnprintf is used. Here's an example:
switch (dev->type) {
case ARPHRD_ETHER:
nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
ntohs(eth_hdr(skb)->h_proto));
return;
default:
break;
}
I am trying to generate arp requests from within the kernel but I do not understand the difference between the 'target MAC address' and the 'destination MAC address'. The kernel function that I am using is this one:
void arp_send(int type, int ptype, __be32 dest_ip,
struct net_device *dev, __be32 src_ip,
const unsigned char *dest_hw, const unsigned char *src_hw,
const unsigned char *target_hw)
Does anyone know the difference between 'target_hw' (the target MAC address) and 'dst_hw' (the destination MAC address)? For me they should be the same...
The arp_send function is a generic one, used to send both ARP requests and responses.
In your case (ARP request) the target_hw is the information you want to learn, so this field can be ignored (set to NULL, see RFC826 example)
dest_hw will also be NULL - which will result in using broadcast address (see arp_create comment)
I'm assuming IPv4 over Ethernet here. For other Layer2/3 protocols it might look different.
I'm reading in the first Bytes of an File with fread:
fread(&example_struct, sizeof(example_struct), 1, fp_input);
Which ends up with different results under linux and solaris? Whereby the example_struct (Elf32_Ehdr) is part of Standart GNU C Liborary defined in elf.h? I would be happy to know why this happens?
General the struct looks the following:
typedef struct
{
unsigned char e_ident[LENGTH];
TYPE_Half e_type;
} example_struct;
The Debugcode:
for(i=0;paul<sizeof(example_struct);i++){
printf("example_struct->e_ident[%i]:(%x) \n",i,example_struct.e_ident[i]);
}
printf("example_struct->e_type: (%x) \n",example_struct.e_type);
printf("example_struct->e_machine: (%x) \n",example_struct.e_machine);
Solaris output:
Elf32_Ehead->e_ident[0]: (7f)
Elf32_Ehead->e_ident[1]: (45)
...
Elf32_Ehead->e_ident[16]: (2)
Elf32_Ehead->e_ident[17]: (0)
...
Elf32_Ehead->e_type: (200)
Elf32_Ehead->e_machine: (6900)
Linux output:
Elf32_Ehead->e_ident[0]: (7f)
Elf32_Ehead->e_ident[1]: (45)
...
Elf32_Ehead->e_ident[16]: (2)
Elf32_Ehead->e_ident[17]: (0)
...
Elf32_Ehead->e_type: (2)
Elf32_Ehead->e_machine: (69)
Maybe similar to: http://forums.devarticles.com/c-c-help-52/file-io-linux-and-solaris-108308.html
You don't mention what CPU you have in the machines, maybe Sparc64 in the Solaris machine and x86_64 in the Linux box, but I would guess that you're having an endianness issue. Intel, ARM and most other common architectures today are what is known as little-endian, the Sparc architecture is big-endian.
Let's assume we have the value 0x1234 in a CPU register and we want to store it in memory (or on hard drive, it doesn't matter where). Let N be the memory address we want to write to. We will need to store this 16 bit integer as two bytes in memory, here comes the confusing part:
Using a big-endian machine will store 0x12 at address N and 0x34 at address N+1.
A little-endian machine will store 0x34 at address N and 0x12 at address N+1.
If we store a value using a little endian machine and read it back using a big endian machine we will have swapped the two bytes around and you'll get the issue that you are seeing.
Probably because of differences in the structure packing between the two platforms. It's a bad idea to read structures directly (as units) from external media, since issues like these tend to pop up.
Why is the IPv4's decimal value different with inet_pton and inet_addr (1734763876) than what you get if you use these 2 websites (1684366951) ?
struct sockaddr_in sin;
inet_pton(AF_INET, "100.101.102.103", &(sin.sin_addr));
printf("%i\n%i\n", inet_addr("100.101.102.103"), sin.sin_addr);
http://www.allredroster.com/iptodec.htm
http://www.ipaddresslocation.org/convertip.php
Endianness - they have the four bytes in opposite orders:
1734763876 = 0x67 66 65 64
1684366951 = 0x64 65 66 67
The value you'll need to use for URLs etc. is the one in 'Network' order, Most-Significant-Byte first. Use htonl() (host-to-network-long) to convert the value, i.e.
printf("%i\n%i\n", htonl(inet_addr("100.101.102.103")), htonl(sin.sin_addr));
caf points out below that I probably have this backwards: the issue is really that you need to convert the network-order data from the socket functions back into host-order for display, i.e.
printf("%i\n%i\n", ntohl(inet_addr("100.101.102.103")), ntohl(sin.sin_addr));
inet_addr gives the result in network-byte order.
1684366951 and 1734763876 are the same number ;-) if you change the endianess.