Revision 1a0ca1e1 slirp/slirp.c

b/slirp/slirp.c
31 31
struct in_addr loopback_addr;
32 32

  
33 33
/* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
34
static const uint8_t special_ethaddr[6] = {
34
static const uint8_t special_ethaddr[ETH_ALEN] = {
35 35
    0x52, 0x55, 0x00, 0x00, 0x00, 0x00
36 36
};
37 37

  
38
static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
38
static const uint8_t zero_ethaddr[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
39 39

  
40 40
/* XXX: suppress those select globals */
41 41
fd_set *global_readfds, *global_writefds, *global_xfds;
......
599 599
	 global_xfds = NULL;
600 600
}
601 601

  
602
#define ETH_ALEN 6
603
#define ETH_HLEN 14
604

  
605
#define ETH_P_IP	0x0800		/* Internet Protocol packet	*/
606
#define ETH_P_ARP	0x0806		/* Address Resolution packet	*/
607

  
608
#define	ARPOP_REQUEST	1		/* ARP request			*/
609
#define	ARPOP_REPLY	2		/* ARP reply			*/
610

  
611
struct ethhdr
612
{
613
	unsigned char	h_dest[ETH_ALEN];	/* destination eth addr	*/
614
	unsigned char	h_source[ETH_ALEN];	/* source ether addr	*/
615
	unsigned short	h_proto;		/* packet type ID field	*/
616
};
617

  
618
struct arphdr
619
{
620
	unsigned short	ar_hrd;		/* format of hardware address	*/
621
	unsigned short	ar_pro;		/* format of protocol address	*/
622
	unsigned char	ar_hln;		/* length of hardware address	*/
623
	unsigned char	ar_pln;		/* length of protocol address	*/
624
	unsigned short	ar_op;		/* ARP opcode (command)		*/
625

  
626
	 /*
627
	  *	 Ethernet looks like this : This bit is variable sized however...
628
	  */
629
	unsigned char		ar_sha[ETH_ALEN];	/* sender hardware address	*/
630
	uint32_t		ar_sip;			/* sender IP address		*/
631
	unsigned char		ar_tha[ETH_ALEN];	/* target hardware address	*/
632
	uint32_t		ar_tip	;		/* target IP address		*/
633
} __attribute__((packed));
634

  
635 602
static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
636 603
{
637
    struct ethhdr *eh = (struct ethhdr *)pkt;
638 604
    struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
639 605
    uint8_t arp_reply[max(ETH_HLEN + sizeof(struct arphdr), 64)];
640 606
    struct ethhdr *reh = (struct ethhdr *)arp_reply;
......
645 611
    ar_op = ntohs(ah->ar_op);
646 612
    switch(ar_op) {
647 613
    case ARPOP_REQUEST:
614
        if (ah->ar_tip == ah->ar_sip) {
615
            /* Gratuitous ARP */
616
            arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
617
            return;
618
        }
619

  
648 620
        if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
649 621
            slirp->vnetwork_addr.s_addr) {
650 622
            if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
......
657 629
            return;
658 630
        arp_ok:
659 631
            memset(arp_reply, 0, sizeof(arp_reply));
660
            /* XXX: make an ARP request to have the client address */
661
            memcpy(slirp->client_ethaddr, eh->h_source, ETH_ALEN);
632

  
633
            arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
662 634

  
663 635
            /* ARP request for alias/dns mac address */
664 636
            memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
......
679 651
        }
680 652
        break;
681 653
    case ARPOP_REPLY:
682
        /* reply to request of client mac address ? */
683
        if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) &&
684
            ah->ar_sip == slirp->client_ipaddr.s_addr) {
685
            memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN);
686
        }
654
        arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
687 655
        break;
688 656
    default:
689 657
        break;
......
729 697
{
730 698
    uint8_t buf[1600];
731 699
    struct ethhdr *eh = (struct ethhdr *)buf;
700
    uint8_t ethaddr[ETH_ALEN];
701
    const struct ip *iph = (const struct ip *)ip_data;
732 702

  
733 703
    if (ip_data_len + ETH_HLEN > sizeof(buf))
734 704
        return;
735
    
736
    if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN)) {
705

  
706
    if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) {
737 707
        uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
738 708
        struct ethhdr *reh = (struct ethhdr *)arp_req;
739 709
        struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
740
        const struct ip *iph = (const struct ip *)ip_data;
741 710

  
742 711
        /* If the client addr is not known, there is no point in
743 712
           sending the packet to it. Normally the sender should have
......
765 734
        slirp->client_ipaddr = iph->ip_dst;
766 735
        slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
767 736
    } else {
768
        memcpy(eh->h_dest, slirp->client_ethaddr, ETH_ALEN);
737
        memcpy(eh->h_dest, ethaddr, ETH_ALEN);
769 738
        memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
770 739
        /* XXX: not correct */
771 740
        memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);

Also available in: Unified diff