mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 13:51:26 +02:00
MINOR: quic: move IP_PKTINFO on send on a dedicated function
When using listener socket, source address for emission is explicitely set using ancillary data for sendmsg(). This is useful to guarantee the correct address is used when binding on a non-explicit address. This code was implemented directly under qc_snd_buf(). However, it is quite complex due to portability issue. For IPv4, two parallel implementations coexist, defined under IP_PKTINFO or IP_RECVDSTADDR. For IPv6, another option is defined under IPV6_RECVPKTINFO. Each variant uses its distinct name which increase the code complexity. Extract ancillary data filling in a dedicated function named cmsg_set_saddr(). This reduces greatly the body of qc_snd_buf(). Such functions can be replicated when other ancillary data type will be implemented. This will notably be useful for GSO implementation.
This commit is contained in:
parent
107d6d7546
commit
ea90c39302
140
src/quic_sock.c
140
src/quic_sock.c
@ -566,6 +566,86 @@ void quic_conn_sock_fd_iocb(int fd)
|
|||||||
TRACE_LEAVE(QUIC_EV_CONN_RCV, qc);
|
TRACE_LEAVE(QUIC_EV_CONN_RCV, qc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cmsg_set_saddr(struct msghdr *msg, struct cmsghdr **cmsg,
|
||||||
|
struct sockaddr_storage *saddr)
|
||||||
|
{
|
||||||
|
struct cmsghdr *c;
|
||||||
|
#ifdef IP_PKTINFO
|
||||||
|
struct in_pktinfo *in;
|
||||||
|
#endif /* IP_PKTINFO */
|
||||||
|
#ifdef IPV6_RECVPKTINFO
|
||||||
|
struct in6_pktinfo *in6;
|
||||||
|
#endif /* IPV6_RECVPKTINFO */
|
||||||
|
size_t sz = 0;
|
||||||
|
|
||||||
|
/* First determine size of ancillary data depending on the system support. */
|
||||||
|
switch (saddr->ss_family) {
|
||||||
|
case AF_INET:
|
||||||
|
#if defined(IP_PKTINFO)
|
||||||
|
sz = sizeof(struct in_pktinfo);
|
||||||
|
#elif defined(IP_RECVDSTADDR)
|
||||||
|
sz = sizeof(struct in_addr);
|
||||||
|
#endif /* IP_PKTINFO || IP_RECVDSTADDR */
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
#ifdef IPV6_RECVPKTINFO
|
||||||
|
sz = sizeof(struct in6_pktinfo);
|
||||||
|
#endif /* IPV6_RECVPKTINFO */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Size is null if system does not support send source address setting. */
|
||||||
|
if (!sz)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Set first msg_controllen to be able to use CMSG_* macros. */
|
||||||
|
msg->msg_controllen += CMSG_SPACE(sz);
|
||||||
|
|
||||||
|
*cmsg = !(*cmsg) ? CMSG_FIRSTHDR(msg) : CMSG_NXTHDR(msg, *cmsg);
|
||||||
|
ALREADY_CHECKED(*cmsg);
|
||||||
|
c = *cmsg;
|
||||||
|
c->cmsg_len = CMSG_LEN(sz);
|
||||||
|
|
||||||
|
switch (saddr->ss_family) {
|
||||||
|
case AF_INET:
|
||||||
|
c->cmsg_level = IPPROTO_IP;
|
||||||
|
#if defined(IP_PKTINFO)
|
||||||
|
c->cmsg_type = IP_PKTINFO;
|
||||||
|
in = (struct in_pktinfo *)CMSG_DATA(c);
|
||||||
|
in->ipi_ifindex = 0;
|
||||||
|
in->ipi_addr.s_addr = 0;
|
||||||
|
memcpy(&in->ipi_spec_dst,
|
||||||
|
&((struct sockaddr_in *)saddr)->sin_addr,
|
||||||
|
sizeof(struct in_addr));
|
||||||
|
#elif defined(IP_RECVDSTADDR)
|
||||||
|
c->cmsg_type = IP_SENDSRCADDR;
|
||||||
|
memcpy(CMSG_DATA(c),
|
||||||
|
&((struct sockaddr_in *)saddr)->sin_addr,
|
||||||
|
sizeof(struct in_addr));
|
||||||
|
#endif /* IP_PKTINFO || IP_RECVDSTADDR */
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AF_INET6:
|
||||||
|
#ifdef IPV6_RECVPKTINFO
|
||||||
|
c->cmsg_level = IPPROTO_IPV6;
|
||||||
|
c->cmsg_type = IPV6_PKTINFO;
|
||||||
|
in6 = (struct in6_pktinfo *)CMSG_DATA(c);
|
||||||
|
in6->ipi6_ifindex = 0;
|
||||||
|
memcpy(&in6->ipi6_addr,
|
||||||
|
&((struct sockaddr_in6 *)saddr)->sin6_addr,
|
||||||
|
sizeof(struct in6_addr));
|
||||||
|
#endif /* IPV6_RECVPKTINFO */
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Send a datagram stored into <buf> buffer with <sz> as size.
|
/* Send a datagram stored into <buf> buffer with <sz> as size.
|
||||||
* The caller must ensure there is at least <sz> bytes in this buffer.
|
* The caller must ensure there is at least <sz> bytes in this buffer.
|
||||||
*
|
*
|
||||||
@ -594,13 +674,7 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz,
|
|||||||
else if (is_addr(&qc->local_addr)) {
|
else if (is_addr(&qc->local_addr)) {
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
struct iovec vec;
|
struct iovec vec;
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg = NULL;
|
||||||
#ifdef IP_PKTINFO
|
|
||||||
struct in_pktinfo *in;
|
|
||||||
#endif /* IP_PKTINFO */
|
|
||||||
#ifdef IPV6_RECVPKTINFO
|
|
||||||
struct in6_pktinfo *in6;
|
|
||||||
#endif /* IPV6_RECVPKTINFO */
|
|
||||||
union {
|
union {
|
||||||
#ifdef IP_PKTINFO
|
#ifdef IP_PKTINFO
|
||||||
char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||||
@ -619,58 +693,8 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz,
|
|||||||
msg.msg_iov = &vec;
|
msg.msg_iov = &vec;
|
||||||
msg.msg_iovlen = 1;
|
msg.msg_iovlen = 1;
|
||||||
|
|
||||||
switch (qc->local_addr.ss_family) {
|
|
||||||
case AF_INET:
|
|
||||||
#if defined(IP_PKTINFO)
|
|
||||||
msg.msg_control = u.buf;
|
|
||||||
msg.msg_controllen = sizeof(u.buf);
|
|
||||||
|
|
||||||
cmsg = CMSG_FIRSTHDR(&msg);
|
|
||||||
in = (struct in_pktinfo *)CMSG_DATA(cmsg);
|
|
||||||
in->ipi_ifindex = 0;
|
|
||||||
in->ipi_addr.s_addr = 0;
|
|
||||||
memcpy(&in->ipi_spec_dst,
|
|
||||||
&((struct sockaddr_in *)&qc->local_addr)->sin_addr,
|
|
||||||
sizeof(struct in_addr));
|
|
||||||
|
|
||||||
cmsg->cmsg_level = IPPROTO_IP;
|
|
||||||
cmsg->cmsg_type = IP_PKTINFO;
|
|
||||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
|
|
||||||
#elif defined(IP_RECVDSTADDR)
|
|
||||||
msg.msg_control = u.bufaddr;
|
msg.msg_control = u.bufaddr;
|
||||||
msg.msg_controllen = sizeof(u.bufaddr);
|
cmsg_set_saddr(&msg, &cmsg, &qc->local_addr);
|
||||||
|
|
||||||
cmsg = CMSG_FIRSTHDR(&msg);
|
|
||||||
cmsg->cmsg_level = IPPROTO_IP;
|
|
||||||
cmsg->cmsg_type = IP_SENDSRCADDR;
|
|
||||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
|
|
||||||
memcpy(CMSG_DATA(cmsg),
|
|
||||||
&((struct sockaddr_in *)&qc->local_addr)->sin_addr,
|
|
||||||
sizeof(struct in_addr));
|
|
||||||
#endif /* IP_PKTINFO || IP_RECVDSTADDR */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AF_INET6:
|
|
||||||
#ifdef IPV6_RECVPKTINFO
|
|
||||||
msg.msg_control = u.buf6;
|
|
||||||
msg.msg_controllen = sizeof(u.buf6);
|
|
||||||
|
|
||||||
cmsg = CMSG_FIRSTHDR(&msg);
|
|
||||||
in6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
|
|
||||||
in6->ipi6_ifindex = 0;
|
|
||||||
memcpy(&in6->ipi6_addr,
|
|
||||||
&((struct sockaddr_in6 *)&qc->local_addr)->sin6_addr,
|
|
||||||
sizeof(struct in6_addr));
|
|
||||||
|
|
||||||
cmsg->cmsg_level = IPPROTO_IPV6;
|
|
||||||
cmsg->cmsg_type = IPV6_PKTINFO;
|
|
||||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
|
||||||
#endif /* IPV6_RECVPKTINFO */
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = sendmsg(qc->li->rx.fd, &msg,
|
ret = sendmsg(qc->li->rx.fd, &msg,
|
||||||
MSG_DONTWAIT|MSG_NOSIGNAL);
|
MSG_DONTWAIT|MSG_NOSIGNAL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user