From patchwork Tue Mar 15 09:42:50 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Thibault X-Patchwork-Id: 8586671 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 8389CC0553 for ; Tue, 15 Mar 2016 09:50:06 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B7C7720259 for ; Tue, 15 Mar 2016 09:50:05 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7C48D20254 for ; Tue, 15 Mar 2016 09:50:04 +0000 (UTC) Received: from localhost ([::1]:46814 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aflc3-0003gy-Tp for patchwork-qemu-devel@patchwork.kernel.org; Tue, 15 Mar 2016 05:50:03 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46965) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aflVM-00084P-TR for qemu-devel@nongnu.org; Tue, 15 Mar 2016 05:43:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aflVK-0002fc-Fb for qemu-devel@nongnu.org; Tue, 15 Mar 2016 05:43:08 -0400 Received: from mail3-relais-sop.national.inria.fr ([192.134.164.104]:16383) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aflVK-0002en-7S for qemu-devel@nongnu.org; Tue, 15 Mar 2016 05:43:06 -0400 X-IronPort-AV: E=Sophos;i="5.24,338,1454972400"; d="scan'208";a="168702201" Received: from unknown (HELO var.youpi.perso.aquilenet.fr) ([193.50.110.81]) by mail3-relais-sop.national.inria.fr with ESMTP/TLS/AES128-GCM-SHA256; 15 Mar 2016 10:43:02 +0100 Received: from samy by var.youpi.perso.aquilenet.fr with local (Exim 4.86_2) (envelope-from ) id 1aflVE-0007jJ-8n; Tue, 15 Mar 2016 10:43:00 +0100 From: Samuel Thibault To: qemu-devel@nongnu.org, Peter Maydell Date: Tue, 15 Mar 2016 10:42:50 +0100 Message-Id: X-Mailer: git-send-email 2.7.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 192.134.164.104 Cc: Thomas Huth , zhanghailiang , Li Zhijian , Stefan Hajnoczi , Jason Wang , Dave Gilbert , Vasiliy Tolstov , Huangpeng , Yann Bordenave , Gonglei , Jan Kiszka , Samuel Thibault , Guillaume Subiron Subject: [Qemu-devel] [PULL 03/11] slirp: Adding ICMPv6 error sending X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Yann Bordenave Adding icmp6_send_error to send ICMPv6 Error messages. This function is simpler than the v4 version. Adding some calls in various functions to send ICMP errors, when a received packet is too big, or when its hop limit is 0. Signed-off-by: Yann Bordenave Signed-off-by: Samuel Thibault Reviewed-by: Thomas Huth --- slirp/ip6_icmp.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ slirp/ip6_icmp.h | 10 +++++++++ slirp/ip6_input.c | 11 +++++++--- 3 files changed, 84 insertions(+), 3 deletions(-) diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c index 9f3fd4a..9d61349 100644 --- a/slirp/ip6_icmp.c +++ b/slirp/ip6_icmp.c @@ -60,6 +60,72 @@ static void icmp6_send_echoreply(struct mbuf *m, Slirp *slirp, struct ip6 *ip, ip6_output(NULL, t, 0); } +void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code) +{ + Slirp *slirp = m->slirp; + struct mbuf *t; + struct ip6 *ip = mtod(m, struct ip6 *); + + DEBUG_CALL("icmp6_send_error"); + DEBUG_ARGS((dfd, " type = %d, code = %d\n", type, code)); + + if (IN6_IS_ADDR_MULTICAST(&ip->ip_src) || + IN6_IS_ADDR_UNSPECIFIED(&ip->ip_src)) { + /* TODO icmp error? */ + return; + } + + t = m_get(slirp); + + /* IPv6 packet */ + struct ip6 *rip = mtod(t, struct ip6 *); + rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR; + rip->ip_dst = ip->ip_src; +#if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600) + char addrstr[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &rip->ip_dst, addrstr, INET6_ADDRSTRLEN); + DEBUG_ARG("target = %s", addrstr); +#endif + + rip->ip_nh = IPPROTO_ICMPV6; + const int error_data_len = min(m->m_len, + IF_MTU - (sizeof(struct ip6) + ICMP6_ERROR_MINLEN)); + rip->ip_pl = htons(ICMP6_ERROR_MINLEN + error_data_len); + t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl); + + /* ICMPv6 packet */ + t->m_data += sizeof(struct ip6); + struct icmp6 *ricmp = mtod(t, struct icmp6 *); + ricmp->icmp6_type = type; + ricmp->icmp6_code = code; + ricmp->icmp6_cksum = 0; + + switch (type) { + case ICMP6_UNREACH: + case ICMP6_TIMXCEED: + ricmp->icmp6_err.unused = 0; + break; + case ICMP6_TOOBIG: + ricmp->icmp6_err.mtu = htonl(IF_MTU); + break; + case ICMP6_PARAMPROB: + /* TODO: Handle this case */ + break; + default: + g_assert_not_reached(); + break; + } + t->m_data += ICMP6_ERROR_MINLEN; + memcpy(t->m_data, m->m_data, error_data_len); + + /* Checksum */ + t->m_data -= ICMP6_ERROR_MINLEN; + t->m_data -= sizeof(struct ip6); + ricmp->icmp6_cksum = ip6_cksum(t); + + ip6_output(NULL, t, 0); +} + /* * Send NDP Router Advertisement */ diff --git a/slirp/ip6_icmp.h b/slirp/ip6_icmp.h index b2c40d6..9460bf8 100644 --- a/slirp/ip6_icmp.h +++ b/slirp/ip6_icmp.h @@ -19,6 +19,12 @@ struct icmp6_echo { /* Echo Messages */ uint16_t seq_num; }; +union icmp6_error_body { + uint32_t unused; + uint32_t pointer; + uint32_t mtu; +}; + /* * NDP Messages */ @@ -82,6 +88,7 @@ struct icmp6 { uint8_t icmp6_code; /* type sub code */ uint16_t icmp6_cksum; /* ones complement cksum of struct */ union { + union icmp6_error_body error_body; struct icmp6_echo echo; struct ndp_rs ndp_rs; struct ndp_ra ndp_ra; @@ -89,6 +96,7 @@ struct icmp6 { struct ndp_na ndp_na; struct ndp_redirect ndp_redirect; } icmp6_body; +#define icmp6_err icmp6_body.error_body #define icmp6_echo icmp6_body.echo #define icmp6_nrs icmp6_body.ndp_rs #define icmp6_nra icmp6_body.ndp_ra @@ -98,6 +106,7 @@ struct icmp6 { } QEMU_PACKED; #define ICMP6_MINLEN 4 +#define ICMP6_ERROR_MINLEN 8 #define ICMP6_ECHO_MINLEN 8 #define ICMP6_NDP_RS_MINLEN 8 #define ICMP6_NDP_RA_MINLEN 16 @@ -197,6 +206,7 @@ struct ndpopt { void icmp6_init(Slirp *slirp); void icmp6_cleanup(Slirp *slirp); void icmp6_input(struct mbuf *); +void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code); void ndp_send_ra(Slirp *slirp); void ndp_send_ns(Slirp *slirp, struct in6_addr addr); diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c index ca0007c..b6a438d 100644 --- a/slirp/ip6_input.c +++ b/slirp/ip6_input.c @@ -39,9 +39,14 @@ void ip6_input(struct mbuf *m) goto bad; } + if (ntohs(ip6->ip_pl) > IF_MTU) { + icmp6_send_error(m, ICMP6_TOOBIG, 0); + goto bad; + } + /* check ip_ttl for a correct ICMP reply */ if (ip6->ip_hl == 0) { - /*icmp_send_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");*/ + icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS); goto bad; } @@ -50,10 +55,10 @@ void ip6_input(struct mbuf *m) */ switch (ip6->ip_nh) { case IPPROTO_TCP: - /*tcp_input(m, hlen, (struct socket *)NULL);*/ + icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE); break; case IPPROTO_UDP: - /*udp_input(m, hlen);*/ + icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE); break; case IPPROTO_ICMPV6: icmp6_input(m);