Problems packing sockaddr_storage
Hi,
Running into a weird issue when packing sockaddr_storage with either v4 or v6 address. To demonstrate the problem, I created a sample test program (limiting it to v4 only addresses). The problem was observed on MAC OS 10.5.8 and Linux RHEL kernel 2.6.9-42 with gcc as the compiler.
Appreciate any help on the issue.
--------Issue description
* Function packAddrs() runs a for loop packing v4 addresses into a single structure. The input address is same for every iteration, output memory size is adjusted using realloc.
* After successfully packing an address, it prints the packed structure contents using displayPackedAddrs()
* The output is fine for first two iterations. However, at the 3rd iteration, the packed contents seem to have got corrupted. It prints only the first packed address.
I have tried using (malloc and memcpy) instead of realloc but no improvement.
Included below is the code and execution output.
--------Test code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
void displayPackAddrs (const struct sockaddr_storage * packedAddrs,
const int packedCount)
{
struct sockaddr_storage *p = packedAddrs;
struct sockaddr_in *sin;
int counter = 0;
int addrPosition = 0;
char str[INET_ADDRSTRLEN];
printf ("Display start\n");
for (counter = 0; counter < packedCount; counter++)
{
p = (packedAddrs+addrPosition);
switch (p->ss_family)
{
case AF_INET:
sin = (struct sockaddr_in *) p;
printf ("Loop no %d addr-size %d addr-string %s \n", counter, sizeof(*sin),
inet_ntop (AF_INET, &(sin->sin_addr), str, INET_ADDRSTRLEN));
addrPosition += sizeof(*sin);
break;
default:
printf ("Loop no %d Unknown addr family %d \n", counter,
p->ss_family);
break;
}
}
printf ("Display end\n\n");
}
const struct addrinfo * const getAddrInfo (const char * const address,
const int aifamily, const int aiprotocol, const int port)
{
struct addrinfo hints, *hintresult;
memset (&hints, 0, sizeof(hints));
hints.ai_family = aifamily;
hints.ai_protocol = aiprotocol;
hints.ai_socktype = SOCK_STREAM;
char portBuf[100];
sprintf (portBuf, "%d", port);
int retValue = getaddrinfo (address, portBuf, &hints, &hintresult);
if (retValue != 0)
{
printf ("Failed to get getaddrinfo, error is %s \n", gai_strerror (
retValue));
return NULL;
}
return hintresult;
}
void packAddrs ()
{
struct sockaddr_storage *packedAddrs = NULL;
int packedCount = 0;
int addrPosition = 0;
int counter = 0;
struct addrinfo *ai = NULL;
for (counter = 0; counter < 3; counter++)
{
ai = getAddrInfo ("127.0.0.1", AF_INET, 6, 2555);
if (NULL != ai)
{
printf ("Packing at position %d addr-size %d \n", addrPosition, ai->ai_addrlen);
packedAddrs = realloc (packedAddrs, addrPosition + ai->ai_addrlen);
if (packedAddrs == NULL)
{
printf ("Realloc failed\n");
exit (-1);
}
memcpy ((packedAddrs + addrPosition), ai->ai_addr, ai->ai_addrlen);
++packedCount;
addrPosition += ai->ai_addrlen;
displayPackAddrs (packedAddrs, packedCount);
}
}
}
int main ()
{
packAddrs ();
}
--------Execution output
Packing at position 0 addr-size 16
Display start
Loop no 0 addr-size 16 addr-string 127.0.0.1
Display end
Packing at position 16 addr-size 16
Display start
Loop no 0 addr-size 16 addr-string 127.0.0.1
Loop no 1 addr-size 16 addr-string 127.0.0.1
Display end
Packing at position 32 addr-size 16
Display start
Loop no 0 addr-size 16 addr-string 127.0.0.1
Loop no 1 Unknown addr family 0
Loop no 2 Unknown addr family 0
Display end
(EOM)
|