MT#55283 add recvfrom_to family

Similar to recvfrom_ts, this return the local (destination) address of
the received packet, extracted from the PKTINFO struct.

Change-Id: Icfed12eb7d9bf6c9d707318e85363fcff8d9aca6
pull/1759/head
Richard Fuchs 2 years ago
parent 16dde52776
commit 8328c0b606

@ -37,6 +37,8 @@ static int __ip4_addrport2sockaddr(void *, const sockaddr_t *, unsigned int);
static int __ip6_addrport2sockaddr(void *, const sockaddr_t *, unsigned int);
static ssize_t __ip_recvfrom(socket_t *s, void *buf, size_t len, endpoint_t *ep);
static ssize_t __ip_recvfrom_ts(socket_t *s, void *buf, size_t len, endpoint_t *ep, struct timeval *);
static ssize_t __ip4_recvfrom_to(socket_t *s, void *buf, size_t len, endpoint_t *ep, sockaddr_t *to);
static ssize_t __ip6_recvfrom_to(socket_t *s, void *buf, size_t len, endpoint_t *ep, sockaddr_t *to);
static ssize_t __ip_sendmsg(socket_t *s, struct msghdr *mh, const endpoint_t *ep);
static ssize_t __ip_sendto(socket_t *s, const void *buf, size_t len, const endpoint_t *ep);
static int __ip4_tos(socket_t *, unsigned int);
@ -86,6 +88,7 @@ static struct socket_family __socket_families[__SF_LAST] = {
.pktinfo = __ip4_pktinfo,
.recvfrom = __ip_recvfrom,
.recvfrom_ts = __ip_recvfrom_ts,
.recvfrom_to = __ip4_recvfrom_to,
.sendmsg = __ip_sendmsg,
.sendto = __ip_sendto,
.tos = __ip4_tos,
@ -119,6 +122,7 @@ static struct socket_family __socket_families[__SF_LAST] = {
.pktinfo = __ip6_pktinfo,
.recvfrom = __ip_recvfrom,
.recvfrom_ts = __ip_recvfrom_ts,
.recvfrom_to = __ip6_recvfrom_to,
.sendmsg = __ip_sendmsg,
.sendto = __ip_sendto,
.tos = __ip6_tos,
@ -304,7 +308,9 @@ static int __ip_accept(socket_t *s, socket_t *newsock) {
return 0;
}
INLINE ssize_t __ip_recvfrom_options(socket_t *s, void *buf, size_t len, endpoint_t *ep, struct timeval *tv) {
INLINE ssize_t __ip_recvfrom_options(socket_t *s, void *buf, size_t len, endpoint_t *ep, struct timeval *tv,
sockaddr_t *to, bool (*parse)(struct cmsghdr *, sockaddr_t *))
{
ssize_t ret;
struct sockaddr_storage sin;
struct msghdr msg;
@ -328,18 +334,23 @@ INLINE ssize_t __ip_recvfrom_options(socket_t *s, void *buf, size_t len, endpoin
return ret;
s->family->sockaddr2endpoint(ep, &sin);
if (tv) {
if (tv || to) {
for (cm = CMSG_FIRSTHDR(&msg); cm; cm = CMSG_NXTHDR(&msg, cm)) {
if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SO_TIMESTAMP) {
if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SO_TIMESTAMP && tv) {
*tv = *((struct timeval *) CMSG_DATA(cm));
tv = NULL;
break;
}
if (parse && to && parse(cm, to))
to = NULL;
}
if (G_UNLIKELY(tv)) {
ilog(LOG_WARNING, "No receive timestamp received from kernel");
ZERO(*tv);
}
if (G_UNLIKELY(to)) {
ilog(LOG_WARNING, "No local address received from kernel");
ZERO(*to);
}
}
if (G_UNLIKELY((msg.msg_flags & MSG_TRUNC)))
ilog(LOG_WARNING, "Kernel indicates that data was truncated");
@ -349,10 +360,32 @@ INLINE ssize_t __ip_recvfrom_options(socket_t *s, void *buf, size_t len, endpoin
return ret;
}
static ssize_t __ip_recvfrom_ts(socket_t *s, void *buf, size_t len, endpoint_t *ep, struct timeval *tv) {
return __ip_recvfrom_options(s, buf, len, ep, tv);
return __ip_recvfrom_options(s, buf, len, ep, tv, NULL, NULL);
}
static ssize_t __ip_recvfrom(socket_t *s, void *buf, size_t len, endpoint_t *ep) {
return __ip_recvfrom_options(s, buf, len, ep, NULL);
return __ip_recvfrom_options(s, buf, len, ep, NULL, NULL, NULL);
}
INLINE bool __ip4_pktinfo_parse(struct cmsghdr *cm, sockaddr_t *to) {
if (cm->cmsg_level != IPPROTO_IP || cm->cmsg_type != IP_PKTINFO)
return false;
struct in_pktinfo *pi = (void *) CMSG_DATA(cm);
to->u.ipv4 = pi->ipi_addr;
to->family = __get_socket_family_enum(SF_IP4);
return true;
}
INLINE bool __ip6_pktinfo_parse(struct cmsghdr *cm, sockaddr_t *to) {
if (cm->cmsg_level != IPPROTO_IPV6 || cm->cmsg_type != IPV6_PKTINFO)
return false;
struct in6_pktinfo *pi = (void *) CMSG_DATA(cm);
to->u.ipv6 = pi->ipi6_addr;
to->family = __get_socket_family_enum(SF_IP6);
return true;
}
static ssize_t __ip4_recvfrom_to(socket_t *s, void *buf, size_t len, endpoint_t *ep, sockaddr_t *to) {
return __ip_recvfrom_options(s, buf, len, ep, NULL, to, __ip4_pktinfo_parse);
}
static ssize_t __ip6_recvfrom_to(socket_t *s, void *buf, size_t len, endpoint_t *ep, sockaddr_t *to) {
return __ip_recvfrom_options(s, buf, len, ep, NULL, to, __ip6_pktinfo_parse);
}
static ssize_t __ip_sendmsg(socket_t *s, struct msghdr *mh, const endpoint_t *ep) {
struct sockaddr_storage sin;

@ -75,6 +75,7 @@ struct socket_family {
int (*pktinfo)(socket_t *);
ssize_t (*recvfrom)(socket_t *, void *, size_t, endpoint_t *);
ssize_t (*recvfrom_ts)(socket_t *, void *, size_t, endpoint_t *, struct timeval *);
ssize_t (*recvfrom_to)(socket_t *, void *, size_t, endpoint_t *, sockaddr_t *);
ssize_t (*sendmsg)(socket_t *, struct msghdr *, const endpoint_t *);
ssize_t (*sendto)(socket_t *, const void *, size_t, const endpoint_t *);
int (*tos)(socket_t *, unsigned int);
@ -169,6 +170,7 @@ INLINE int is_addr_unspecified(const sockaddr_t *a) {
}
#define socket_recvfrom(s,a...) (s)->family->recvfrom((s), a)
#define socket_recvfrom_ts(s,a...) (s)->family->recvfrom_ts((s), a)
#define socket_recvfrom_to(s,a...) (s)->family->recvfrom_to((s), a)
#define socket_sendmsg(s,a...) (s)->family->sendmsg((s), a)
#define socket_sendto(s,a...) (s)->family->sendto((s), a)
#define socket_error(s) (s)->family->error((s))

Loading…
Cancel
Save