From: 7ppKb5bW <pONy4THS@protonmail.com>
To: "jmaloy@redhat.com" <jmaloy@redhat.com>
Cc: "passt-dev@passt.top" <passt-dev@passt.top>
Subject: Re: [PATCH v8 2/4] udp: create and send ICMPv4 to local peer when applicable
Date: Mon, 03 Mar 2025 12:07:54 +0000 [thread overview]
Message-ID: <qvsmfk-cFWFekWKR42S1CwSbiHtcYrCMojG2VWocRU-gGFuTslpSlSt40Q277ZV1xXNrL2h-zTkgA3wqUevL25Tum9iHZ3h02VSZe9yEqLU=@protonmail.com> (raw)
> +/**
> + * udp_send_conn_fail_icmp4() - Construct and send ICMPv4 to local peer
> + * @c: Execution context
> + * @ee: Extended error descriptor
> + * @ref: epoll reference
> + * @in: First bytes (max 8) of original UDP message body
> + * @dlen: Length of the read part of original UDP message body
> + */
> +static void udp_send_conn_fail_icmp4(const struct ctx *c,
> + const struct sock_extended_err *ee,
> + const struct flowside *toside,
> + void *in, size_t dlen)
> +{
> + struct in_addr oaddr = toside->oaddr.v4mapped.a4;
> + struct in_addr eaddr = toside->eaddr.v4mapped.a4;
> + in_port_t eport = toside->eport;
> + in_port_t oport = toside->oport;
> + struct {
> + struct icmphdr icmp4h;
> + struct iphdr ip4h;
> + struct udphdr uh;
> + char data[ICMP4_MAX_DLEN];
> + } __attribute__((packed, aligned(__alignof__(max_align_t)))) msg;
> + size_t msglen = sizeof(msg) - sizeof(msg.data) + dlen;
> +
> + ASSERT(dlen <= ICMP4_MAX_DLEN);
> + memset(&msg, 0, sizeof(msg));
> + msg.icmp4h.type = ee->ee_type;
> + msg.icmp4h.code = ee->ee_code;
> + if (ee->ee_type == ICMP_DEST_UNREACH && ee->ee_code == ICMP_FRAG_NEEDED)
> + msg.icmp4h.un.frag.mtu = htons((uint16_t) ee->ee_info);
> +
> + /* Reconstruct the original headers as returned in the ICMP message */
> + tap_push_ip4h(&msg.ip4h, eaddr, oaddr, dlen, IPPROTO_UDP);
> + tap_push_uh4(&msg.uh, eaddr, eport, oaddr, oport, in, dlen);
> + memcpy(&msg.data, in, dlen);
> +
> + tap_icmp4_send(c, oaddr, eaddr, &msg, msglen);
> +}
The destination IP of the origin packet might not be the source IP of an ICMP error message, if a router sent this ICMP error message.
Increase local MTU and try this program:
```
#packet-too-big.py
#ip link set eth0 mtu 1520
from socket import *
import time
IP_RECVERR=0xb
IP_MTU_DISCOVER=0xa
IP_PMTUDISC_PROBE=0x3
with socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP) as sock:
sock.setsockopt(IPPROTO_IP,IP_RECVERR,1)
sock.setsockopt(IPPROTO_IP,IP_MTU_DISCOVER,IP_PMTUDISC_PROBE)
bigPacket=bytes(1480)
sock.sendto(bigPacket,("151.101.1.6",443))
time.sleep(0.1)
print(sock.recvmsg(1480,1024,MSG_ERRQUEUE))
```
> if (ref.type == EPOLL_TYPE_UDP_REPLY) {
> flow_sidx_t sidx = flow_sidx_opposite(ref.flowside);
> const struct flowside *toside = flowside_at_sidx(sidx);
> -
> - udp_send_conn_fail_icmp4(c, ee, toside, data, rc);
> + size_t dlen = rc;
> +
> + if (hdr->cmsg_level == IPPROTO_IP) {
> + dlen = MIN(dlen, ICMP4_MAX_DLEN);
> + udp_send_conn_fail_icmp4(c, ee, toside, data, dlen);
> + } else if (hdr->cmsg_level == IPPROTO_IPV6) {
> + udp_send_conn_fail_icmp6(c, ee, toside, data,
> + dlen, sidx.flowi);
> + }
> } else {
> trace("Ignoring received IP_RECVERR cmsg on listener socket");
> }
If the socket is dual-stack, cmsg_level may not match cmsg_data.
```
#dual-stack-test.py
from socket import *
import time
IP_RECVERR=0xb
with socket(AF_INET6,SOCK_DGRAM,IPPROTO_UDP) as sock:
sock.setsockopt(IPPROTO_IP,IP_RECVERR,1)
sock.setsockopt(IPPROTO_IP,IP_TTL,1)
packet=bytes(8)
sock.sendto(packet,("::ffff:151.101.1.6",443))
time.sleep(0.1)
print(sock.recvmsg(1472,1024,MSG_ERRQUEUE))
```
next reply other threads:[~2025-03-03 12:08 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-03 12:07 7ppKb5bW [this message]
2025-03-03 16:41 ` [PATCH v8 2/4] udp: create and send ICMPv4 to local peer when applicable Jon Maloy
2025-03-04 4:54 ` David Gibson
-- strict thread matches above, loose matches on Subject: below --
2025-02-28 22:41 [PATCH v8 0/4] Reconstruct incoming ICMP headers for failed UDP connect and forward back Jon Maloy
2025-02-28 22:41 ` [PATCH v8 2/4] udp: create and send ICMPv4 to local peer when applicable Jon Maloy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='qvsmfk-cFWFekWKR42S1CwSbiHtcYrCMojG2VWocRU-gGFuTslpSlSt40Q277ZV1xXNrL2h-zTkgA3wqUevL25Tum9iHZ3h02VSZe9yEqLU=@protonmail.com' \
--to=pony4ths@protonmail.com \
--cc=jmaloy@redhat.com \
--cc=passt-dev@passt.top \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).