socket-default: Refactor retrieval of destination address of received packets

This makes the code a bit clearer than with the interleaved ifdefs.
This commit is contained in:
Tobias Brunner 2015-11-02 16:16:56 +01:00
parent 9953e76c3d
commit 99747bed8f
1 changed files with 89 additions and 39 deletions

View File

@ -148,6 +148,91 @@ struct private_socket_default_socket_t {
u_int rr_counter;
};
/**
* Get the destination IPv4 address of a received packet, depending on the
* available mechanism.
*/
#ifdef IP_PKTINFO
static host_t *get_dst_v4(struct cmsghdr *cmsgptr, u_int16_t port)
{
struct sockaddr_in dst = {
.sin_family = AF_INET,
.sin_port = htons(port),
};
struct in_pktinfo *pktinfo;
struct in_addr *addr;
if (cmsgptr->cmsg_type == IP_PKTINFO)
{
pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsgptr);
addr = &pktinfo->ipi_addr;
memcpy(&dst.sin_addr, addr, sizeof(dst.sin_addr));
return host_create_from_sockaddr((sockaddr_t*)&dst);
}
return NULL;
}
#elif defined(IP_RECVDSTADDR)
static host_t *get_dst_v4(struct cmsghdr *cmsgptr, u_int16_t port)
{
struct sockaddr_in dst = {
.sin_family = AF_INET,
.sin_port = htons(port),
};
struct in_addr *addr;
if (cmsgptr->cmsg_type == IP_RECVDSTADDR)
{
addr = (struct in_addr*)CMSG_DATA(cmsgptr);
memcpy(&dst.sin_addr, addr, sizeof(dst.sin_addr));
return host_create_from_sockaddr((sockaddr_t*)&dst);
}
return NULL;
}
#else /* IP_PKTINFO || IP_RECVDSTADDR */
static host_t *get_dst_v4(struct cmsghdr *cmsgptr, u_int16_t port)
{
return NULL;
}
#endif /* IP_PKTINFO || IP_RECVDSTADDR */
/**
* Get the destination IPv6 address of a received packet, depending on the
* available mechanism.
*/
#ifdef HAVE_IN6_PKTINFO
static host_t *get_dst_v6(struct cmsghdr *cmsgptr, u_int16_t port)
{
struct in6_pktinfo *pktinfo;
struct sockaddr_in6 dst = {
.sin6_family = AF_INET6,
.sin6_port = htons(port),
};
if (cmsgptr->cmsg_type == IPV6_PKTINFO)
{
pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
return host_create_from_sockaddr((sockaddr_t*)&dst);
}
return NULL;
}
#else /* HAVE_IN6_PKTINFO */
static host_t *get_dst_v6(struct cmsghdr *cmsgptr, u_int16_t port)
{
return NULL;
}
#endif /* HAVE_IN6_PKTINFO */
METHOD(socket_t, receiver, status_t,
private_socket_default_socket_t *this, packet_t **packet)
{
@ -233,48 +318,13 @@ METHOD(socket_t, receiver, status_t,
DBG1(DBG_NET, "error reading ancillary data");
return FAILED;
}
#ifdef HAVE_IN6_PKTINFO
if (cmsgptr->cmsg_level == SOL_IPV6 &&
cmsgptr->cmsg_type == IPV6_PKTINFO)
if (cmsgptr->cmsg_level == SOL_IP)
{
struct in6_pktinfo *pktinfo;
pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
struct sockaddr_in6 dst;
memset(&dst, 0, sizeof(dst));
memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
dst.sin6_family = AF_INET6;
dst.sin6_port = htons(port);
dest = host_create_from_sockaddr((sockaddr_t*)&dst);
dest = get_dst_v4(cmsgptr, port);
}
#endif /* HAVE_IN6_PKTINFO */
if (cmsgptr->cmsg_level == SOL_IP &&
#ifdef IP_PKTINFO
cmsgptr->cmsg_type == IP_PKTINFO
#elif defined(IP_RECVDSTADDR)
cmsgptr->cmsg_type == IP_RECVDSTADDR
#else
FALSE
#endif
)
else if (cmsgptr->cmsg_level == SOL_IPV6)
{
struct in_addr *addr;
struct sockaddr_in dst;
#ifdef IP_PKTINFO
struct in_pktinfo *pktinfo;
pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsgptr);
addr = &pktinfo->ipi_addr;
#elif defined(IP_RECVDSTADDR)
addr = (struct in_addr*)CMSG_DATA(cmsgptr);
#endif
memset(&dst, 0, sizeof(dst));
memcpy(&dst.sin_addr, addr, sizeof(dst.sin_addr));
dst.sin_family = AF_INET;
dst.sin_port = htons(port);
dest = host_create_from_sockaddr((sockaddr_t*)&dst);
dest = get_dst_v6(cmsgptr, port);
}
if (dest)
{