2

I'm currently setting up a UDP socket for a school assignment but I can't figure out how to properly send sockaddr as a parameter into a function. The input arguments for SendData is defined the same way they are in the sendto function.

void SendData(int fileDescriptor, const struct sockaddr_in *destAddrUdp, unsigned char buffer[MAXMSG])
{
  /* crc */
  int strlength = strlen(buffer);
  unsigned char SCRC = CRC(buffer, strlength-1);
  buffer[strlength-1] = SCRC;
  buffer[strlength] = '\0'; 
  /* send */
  if (sendto(fileDescriptor, buffer, strlen(buffer), 0, (struct sockaddr*) &destAddrUdp,sizeof(destAddrUdp)) < 0) {
    fprintf(stderr, "Could not send data\n");
  }
} `

When the below code is called from main it works however when it's called from SendData the return value from sendto is -1.

if (sendto(fileDescriptor, buffer, strlen(buffer), 0, (struct sockaddr*) &destAddrUdp,sizeof(destAddrUdp)) < 0) {
    fprintf(stderr, "Could not send data\n");
  }

If the program is compiled I get warning: passing argument 5 of ‘recvfrom’ from incompatible pointer type. on the sendto functioncall in SendData. The function call for SendData in my main program is: SendData(sockfd, (struct sockaddr *) &destAddrUdp, buffer);

The main program in case it is relevant:

unsigned char SCRC;
  unsigned char strlength;
  unsigned char buffer[MAXMSG-5];
  unsigned char header[MAXMSG];
  struct rtp_struct *sendstruct; 
  /* option 2 */
  struct sockaddr_in destAddrUdp;
  int sockfd; 
  char dstHost[15]; 
  printf("input host IP:\n>");
  fgets(dstHost, 15, stdin);

  /* Create socket */ 
  if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
    fprintf(stderr, "Can't create UDP socket\n");

  /* set configurations */
  memset (&destAddrUdp, 0, sizeof(destAddrUdp));  //set zero
  destAddrUdp.sin_family = AF_INET; //internet use
  destAddrUdp.sin_addr.s_addr = inet_addr(dstHost); //set so anyone can connect
  destAddrUdp.sin_port = htons(dstUdpPort); //set the port to use

  /* Generate CRC table */
  GenerateCRCTable();

/* get string and send */
while(1) {
    printf("\n>");
    fgets(buffer, MAXMSG, stdin);
    if(strncmp(buffer,"quit\n",MAXMSG) != 0){ //if read string == quit, see else
      strlength = strlen(buffer);
      SCRC = CRC(buffer, strlength-1);
      buffer[strlength-1] = SCRC;
      buffer[strlength] = '\0';

      SendData(sockfd, (struct sockaddr *) &destAddrUdp, buffer);
      /*if (sendto(sockfd, buffer, strlength, 0, (struct sockaddr *) &destAddrUdp,sizeof(destAddrUdp)) < 0){
        fprintf(stderr, "Could not send data\n");}*/
    }  
    else {   
      close(sockfd); 
      exit(EXIT_SUCCESS);
    }
  }
}
Depe
  • 21
  • 2
  • Quick standard remark: Be aware that it is 2017 and you are still writing software which only supports legacy IP addresses. Best to get into the habit of supporting both `sockaddr_in6` and `sockaddr_in` (for legacy IP) in your software. (Once you have figured out your current issue.) – ndim Aug 25 '17 at 23:48
  • Why this `(struct sockaddr *) &destAddrUdp` cast in `main()`? – alk Aug 26 '17 at 08:21

2 Answers2

2

In your SendData function, the parameter destAddrUdp has type const struct sockaddr_in *. When you then make this call:

sendto(fileDescriptor, buffer, strlen(buffer), 0, 
       (struct sockaddr*) &destAddrUdp, sizeof(destAddrUdp)

The expression &destAddrUdp has type const struct sockaddr_in **, so the pointer type is incompatible. Also, sizeof(destAddrUdp) is returning the size of a pointer, not the size of the struct.

You failed to account for the differing types of destAddrUdp in SendData and main. The correct call to sendto would be:

sendto(fileDescriptor, buffer, strlen(buffer), 0, 
       (struct sockaddr*) destAddrUdp, sizeof(*destAddrUdp)
dbush
  • 205,898
  • 23
  • 218
  • 273
  • It is not only the pointer type that is incompatible - this could be fixed with an appropriate cast. The value itself is just wrong, as you do not pass the address of the sockaddr struct but the address of the pointer to the sockaddr struct... – Michael Beer Dec 07 '18 at 09:03
0

The problem is the sizeof(destAddrUdp) and the (struct sockaddr*) &destAddrUdp.

In your main, destAddrUdp is an struct sockaddr_in, in your function however, its a sockaddr_in* so you can't use them equally. First, sizeof(destAddrUdp) in your function will give you the size of a pointer, second, &destAddrUdp in your function will give you a destAddrUdp**. Thats not what you want.

Try sendto(fileDescriptor, buffer, strlen(buffer), 0, (struct sockaddr*) destAddrUdp,sizeof(*destAddrUdp))

tkausl
  • 13,686
  • 2
  • 33
  • 50