From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=pass (p=quarantine dis=none) header.from=protonmail.com Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=protonmail.com header.i=@protonmail.com header.a=rsa-sha256 header.s=protonmail3 header.b=HXH34RA5; dkim-atps=neutral Received: from mail-4027.protonmail.ch (mail-4027.protonmail.ch [185.70.40.27]) by passt.top (Postfix) with ESMTPS id 5B58E5A0623 for ; Mon, 03 Mar 2025 13:08:00 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1741003678; x=1741262878; bh=jZkMHsBf+s5mA7oGXtX7Z80u4XyScgZ2w1Rn0S6iu3g=; h=Date:To:From:Cc:Subject:Message-ID:Feedback-ID:From:To:Cc:Date: Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector: List-Unsubscribe:List-Unsubscribe-Post; b=HXH34RA51mSFk/gk9+IvVIp20JhuVzVUoov5ZDrL1F4+T1ote3TcNFRUAuj/OtPlr yOvp33qZZg+RNrv+01ZuHStzwbMXWR1Exd9LiJAsyC2OP85Xh7QzG+bJehiZchndYO wfQbE48gc18lCjq2oAqHZ9L/0i7aXKVedU8rWE+fMnttd4vwYgVw8YeVbR0u3HRT3l Yv1Gw2vVlMXR9sTbIdPn7dTTMwbsSEQSAmKBfLXS1ZuBC6PiPWTzpBEISjQR6FCRZp oPspsodvJe/2OVetilahPpVK3SuGLwaB9c1qthkfYDxQdBH55aCWthF2+i5lEzHIMu b8kl7HOZtJ/MQ== Date: Mon, 03 Mar 2025 12:07:54 +0000 To: "jmaloy@redhat.com" From: 7ppKb5bW Subject: Re: [PATCH v8 2/4] udp: create and send ICMPv4 to local peer when applicable Message-ID: Feedback-ID: 42387216:user:proton X-Pm-Message-ID: 51d8a95af4b2032f398f5109a25e7b82a72df8eb MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-MailFrom: pONy4THS@protonmail.com X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation Message-ID-Hash: O5G5YSAXVOOYCNQDXLVZUSSAYF7CNYF2 X-Message-ID-Hash: O5G5YSAXVOOYCNQDXLVZUSSAYF7CNYF2 X-Mailman-Approved-At: Mon, 03 Mar 2025 17:10:42 +0100 CC: "passt-dev@passt.top" X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: > +/** > + * udp_send_conn_fail_icmp4() - Construct and send ICMPv4 to local peer > + * @c:=09=09Execution context > + * @ee:=09Extended error descriptor > + * @ref:=09epoll reference > + * @in:=09First bytes (max 8) of original UDP message body > + * @dlen:=09Length of the read part of original UDP message body > + */ > +static void udp_send_conn_fail_icmp4(const struct ctx *c, > +=09=09=09=09 const struct sock_extended_err *ee, > +=09=09=09=09 const struct flowside *toside, > +=09=09=09=09 void *in, size_t dlen) > +{ > +=09struct in_addr oaddr =3D toside->oaddr.v4mapped.a4; > +=09struct in_addr eaddr =3D toside->eaddr.v4mapped.a4; > +=09in_port_t eport =3D toside->eport; > +=09in_port_t oport =3D toside->oport; > +=09struct { > +=09=09struct icmphdr icmp4h; > +=09=09struct iphdr ip4h; > +=09=09struct udphdr uh; > +=09=09char data[ICMP4_MAX_DLEN]; > +=09} __attribute__((packed, aligned(__alignof__(max_align_t)))) msg; > +=09size_t msglen =3D sizeof(msg) - sizeof(msg.data) + dlen; > + > +=09ASSERT(dlen <=3D ICMP4_MAX_DLEN); > +=09memset(&msg, 0, sizeof(msg)); > +=09msg.icmp4h.type =3D ee->ee_type; > +=09msg.icmp4h.code =3D ee->ee_code; > +=09if (ee->ee_type =3D=3D ICMP_DEST_UNREACH && ee->ee_code =3D=3D ICMP_F= RAG_NEEDED) > +=09=09msg.icmp4h.un.frag.mtu =3D htons((uint16_t) ee->ee_info); > + > +=09/* Reconstruct the original headers as returned in the ICMP message *= / > +=09tap_push_ip4h(&msg.ip4h, eaddr, oaddr, dlen, IPPROTO_UDP); > +=09tap_push_uh4(&msg.uh, eaddr, eport, oaddr, oport, in, dlen); > +=09memcpy(&msg.data, in, dlen); > + > +=09tap_icmp4_send(c, oaddr, eaddr, &msg, msglen); > +} The destination IP of the origin packet might not be the source IP of an IC= MP 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=3D0xb IP_MTU_DISCOVER=3D0xa IP_PMTUDISC_PROBE=3D0x3 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=3Dbytes(1480) sock.sendto(bigPacket,("151.101.1.6",443)) time.sleep(0.1) print(sock.recvmsg(1480,1024,MSG_ERRQUEUE)) ``` > =09if (ref.type =3D=3D EPOLL_TYPE_UDP_REPLY) { > =09=09flow_sidx_t sidx =3D flow_sidx_opposite(ref.flowside); > =09=09const struct flowside *toside =3D flowside_at_sidx(sidx); > - > -=09=09udp_send_conn_fail_icmp4(c, ee, toside, data, rc); > +=09=09size_t dlen =3D rc; > + > +=09=09if (hdr->cmsg_level =3D=3D IPPROTO_IP) { > +=09=09=09dlen =3D MIN(dlen, ICMP4_MAX_DLEN); > +=09=09=09udp_send_conn_fail_icmp4(c, ee, toside, data, dlen); > +=09=09} else if (hdr->cmsg_level =3D=3D IPPROTO_IPV6) { > +=09=09=09udp_send_conn_fail_icmp6(c, ee, toside, data, > +=09=09=09=09=09=09 dlen, sidx.flowi); > +=09=09} > =09} else { > =09=09trace("Ignoring received IP_RECVERR cmsg on listener socket"); > =09} If the socket is dual-stack, cmsg_level may not match cmsg_data. ``` #dual-stack-test.py from socket import * import time IP_RECVERR=3D0xb 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=3Dbytes(8) sock.sendto(packet,("::ffff:151.101.1.6",443)) time.sleep(0.1) print(sock.recvmsg(1472,1024,MSG_ERRQUEUE)) ```