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