From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Kqt8K-0001to-RF for qemu-devel@nongnu.org; Fri, 17 Oct 2008 13:29:04 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Kqt8J-0001t5-7Z for qemu-devel@nongnu.org; Fri, 17 Oct 2008 13:29:04 -0400 Received: from [199.232.76.173] (port=60607 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Kqt8I-0001t0-Uu for qemu-devel@nongnu.org; Fri, 17 Oct 2008 13:29:02 -0400 Received: from savannah.gnu.org ([199.232.41.3]:39139 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Kqt8I-0004xx-JR for qemu-devel@nongnu.org; Fri, 17 Oct 2008 13:29:02 -0400 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1Kqt8H-0004ZZ-4H for qemu-devel@nongnu.org; Fri, 17 Oct 2008 17:29:01 +0000 Received: from bellard by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1Kqt8F-0004ZU-QT for qemu-devel@nongnu.org; Fri, 17 Oct 2008 17:29:00 +0000 MIME-Version: 1.0 Errors-To: bellard Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Fabrice Bellard Message-Id: Date: Fri, 17 Oct 2008 17:28:59 +0000 Subject: [Qemu-devel] [5498] allow SLIRP to make an ARP request to get the client MAC address. Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 5498 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5498 Author: bellard Date: 2008-10-17 17:28:58 +0000 (Fri, 17 Oct 2008) Log Message: ----------- allow SLIRP to make an ARP request to get the client MAC address. It is useful if an inbound connection is done to a VM which did not send outbound IP packets Modified Paths: -------------- trunk/slirp/slirp.c Modified: trunk/slirp/slirp.c =================================================================== --- trunk/slirp/slirp.c 2008-10-17 08:08:56 UTC (rev 5497) +++ trunk/slirp/slirp.c 2008-10-17 17:28:58 UTC (rev 5498) @@ -16,8 +16,12 @@ 0x52, 0x54, 0x00, 0x12, 0x35, 0x00 }; +/* ARP cache for the guest IP addresses (XXX: allow many entries) */ uint8_t client_ethaddr[6]; +static struct in_addr client_ipaddr; +static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 }; + int do_slowtimo; int link_up; struct timeval tt; @@ -597,6 +601,13 @@ slirp_output(arp_reply, sizeof(arp_reply)); } break; + case ARPOP_REPLY: + /* reply to request of client mac address ? */ + if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) && + !memcmp(ah->ar_sip, &client_ipaddr.s_addr, 4)) { + memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN); + } + break; default: break; } @@ -641,14 +652,47 @@ if (ip_data_len + ETH_HLEN > sizeof(buf)) return; + + if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) { + uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)]; + struct ethhdr *reh = (struct ethhdr *)arp_req; + struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN); + const struct ip *iph = (const struct ip *)ip_data; - memcpy(eh->h_dest, client_ethaddr, ETH_ALEN); - memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1); - /* XXX: not correct */ - eh->h_source[5] = CTL_ALIAS; - eh->h_proto = htons(ETH_P_IP); - memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); - slirp_output(buf, ip_data_len + ETH_HLEN); + /* If the client addr is not known, there is no point in + sending the packet to it. Normally the sender should have + done an ARP request to get its MAC address. Here we do it + in place of sending the packet and we hope that the sender + will retry sending its packet. */ + memset(reh->h_dest, 0xff, ETH_ALEN); + memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1); + reh->h_source[5] = CTL_ALIAS; + reh->h_proto = htons(ETH_P_ARP); + rah->ar_hrd = htons(1); + rah->ar_pro = htons(ETH_P_IP); + rah->ar_hln = ETH_ALEN; + rah->ar_pln = 4; + rah->ar_op = htons(ARPOP_REQUEST); + /* source hw addr */ + memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1); + rah->ar_sha[5] = CTL_ALIAS; + /* source IP */ + memcpy(rah->ar_sip, &alias_addr, 4); + /* target hw addr (none) */ + memset(rah->ar_tha, 0, ETH_ALEN); + /* target IP */ + memcpy(rah->ar_tip, &iph->ip_dst, 4); + client_ipaddr = iph->ip_dst; + slirp_output(arp_req, sizeof(arp_req)); + } else { + memcpy(eh->h_dest, client_ethaddr, ETH_ALEN); + memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1); + /* XXX: not correct */ + eh->h_source[5] = CTL_ALIAS; + eh->h_proto = htons(ETH_P_IP); + memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); + slirp_output(buf, ip_data_len + ETH_HLEN); + } } int slirp_redir(int is_udp, int host_port,