2

Okay first here is the code:

int recvMast_sock;
struct sockaddr_in serv_addr, cli_addr;
socklen_t cli_len;
if ((recvMast_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
  {
    critErr("listen:socket=");
  }

fillSockaddrAny(&serv_addr, UDP_NODE_LISTEN_PORT);// fills the sockaddr_in works fine elsewhere

if ((bind(recvMast_sock, (struct sockaddr*) &serv_addr, sizeof serv_addr)) < 0)
  {
    critErr("listen:bind recv_mast_sock:");
  }
recvReturn_i = recvfrom(recvMast_sock, &recvBuff[0], (size_t)1, 0, (struct   sockaddr*) &cli_addr, &cli_len);
if(recvReturn_i <0)
        printf("recv error%d\n",errno);

critErr is a function to handle errors which also includes a print of the error and an exit.

This runs in a thread, if this is of any relevance. If I compile and run this on a Zedboard (ZYNQ-7000 SoC) which has an ARM Cortex A9 and Linaro Linux (based on precise Ubuntu). It prints error 22 but still has the received value in recvBuff[0].

Running this in my VM with xubuntu it works fine.

Error 22 equals EINVAL which is described as Invalid argument.

In the manpage of recvfrom(2) it states EINVAL means that the MSG_OOB flag is set but I don't use any flags (passing 0).

Before leaving on friday I started an apt-get upgrade because I hope it is a faulty library or something like this. I can check back at monday but maybe someone here has another idea what is wrong.

Kami Kaze
  • 2,069
  • 15
  • 27
  • 2
    I highly doubt this has something to do with the architecture, instead check that the setup is ok. – Iharob Al Asimi Oct 03 '15 at 11:07
  • setup in what kind of sense. The installation of the linux or the hardware? Networking works normal except for that. Its not the first call to a recvfrom. – Kami Kaze Oct 03 '15 at 11:10
  • Both probably, but I would first check the linux instalation. Are they both the same Ubuntu? – Iharob Al Asimi Oct 03 '15 at 11:11
  • As stated the VM runs a xubuntu (15.04) and the other one is linaro (which is based on precise-Ubuntu) – Kami Kaze Oct 03 '15 at 11:12
  • It seems like an old one, I am no Ubuntu fan but precise is old from what I remember. There might indeed be a bug in some library function. Try installing *linaro* on the virtual machine and check if it still reproduces the problem, if it doesn't you can *maybe* blame the architecture, but I don't see how this particular problem can be related to that. – Iharob Al Asimi Oct 03 '15 at 11:15
  • Mhh i might try that. But linaro is a linux for ARM-processors. Well let's see what monday brings me. I should have titled this with the architecture because i thought there might have been flaws in the libraries or gcc for ARM at some point or you have to care about something on ARM. Whatever... – Kami Kaze Oct 03 '15 at 11:18

2 Answers2

6

You need to initialize cli_len before passing it to recvfrom():

cli_len = sizeof(cli_addr);

You are not initializing it, so it has a random value. If that value happens to be < sizeof(cli_addr), recvfrom() can fail with EINVAL, or at least truncate the address, because it thinks cli_addr is not large enough to receive the client address. If the value is vastly larger than sizeof(cli_addr), recvfrom() might consider the buffer to be outside of the valid memory range.

You have to tell recvfrom() how large cli_addr actually is. This is clearly stated in the documentation:

The argument addrlen is a value-result argument, which the caller should initialize before the call to the size of the buffer associated with src_addr, and modified on return to indicate the actual size of the source address. The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call.

So you have to initialize cli_len with the total size of cli_addr before calling recvfrom(), then recvfrom() updates cli_len with the size of the address that was actually written into cli_addr. cli_addr can be larger than the address, for instance when using a sockaddr_storage structure to accept either IPv4 or IPv6 addresses on a dual-stack socket. In the example in the question, an IPv4 socket is being used, so cli_len must be initialized to a value >= sizeof(sockaddr_in).

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

This was not caused by the OS or the architecture. The function was not called on the x86-system because of a blocked mutex. So I didn't got the error there.

The problem was that I passed the socket to this function from 'main' (which i did not state in the question because I thought it was irrelevant, my bad...) In 'main' I used it and used it in this function. Even though it was mutually exclusive, there was this error.

Remy's answer was also relevant but not a solution to the problem. Not setting cli_len beforehand just leads to a cut of sockaddr if its too small. No error was generated for that.

Kami Kaze
  • 2,069
  • 15
  • 27