public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
* Re: [PATCH v8 2/4] udp: create and send ICMPv4 to local peer when applicable
@ 2025-03-03 12:07 7ppKb5bW
  2025-03-03 16:41 ` Jon Maloy
  0 siblings, 1 reply; 4+ messages in thread
From: 7ppKb5bW @ 2025-03-03 12:07 UTC (permalink / raw)
  To: jmaloy; +Cc: passt-dev

> +/**
> + * 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))

```

^ permalink raw reply	[flat|nested] 4+ messages in thread
* [PATCH v8 0/4] Reconstruct incoming ICMP headers for failed UDP connect and forward back
@ 2025-02-28 22:41 Jon Maloy
  2025-02-28 22:41 ` [PATCH v8 2/4] udp: create and send ICMPv4 to local peer when applicable Jon Maloy
  0 siblings, 1 reply; 4+ messages in thread
From: Jon Maloy @ 2025-02-28 22:41 UTC (permalink / raw)
  To: passt-dev, sbrivio, lvivier, dgibson, jmaloy

v2: - Added patch breaking out udp header creation from function
      tap_udp4_send().
    - Updated the ICMP creation by using the new function.
    - Added logics to find correct flow, depending on origin.
    - All done after feedback from David Gibson.
v3: - More changes after feedback from David Gibson.
v4: - Even more changes after feedback from D. Gibson
v5: - Added corresponding patches for IPv6
v6: - Fixed some small nits after comments from D. Gibson.
v7: - Added handling of all rejected ICMP messages
    - Returning correct user data amount if IPv6 as per RFC 4884.
v8: - Added MTU to ICMPv4 ICMP_FRAG_NEEDED messages.
    - Added ASSERT() validation to message creation functions.

Jon Maloy (4):
  tap: break out building of udp header from tap_udp4_send function
  udp: create and send ICMPv4 to local peer when applicable
  tap: break out building of udp header from tap_udp6_send function
  udp: create and send ICMPv6 to local peer when applicable

 tap.c          |  86 +++++++++++++++++++++++---------
 tap.h          |  15 ++++++
 udp.c          | 132 ++++++++++++++++++++++++++++++++++++++++++++-----
 udp_internal.h |   2 +-
 udp_vu.c       |   4 +-
 5 files changed, 200 insertions(+), 39 deletions(-)

-- 
2.48.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-03-04  4:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-03-03 12:07 [PATCH v8 2/4] udp: create and send ICMPv4 to local peer when applicable 7ppKb5bW
2025-03-03 16:41 ` 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

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).