/* output the IP packet to the ethernet device */ void if_encap(const uint8_t *ip_data, int ip_data_len) { uint8_t buf[1600]; struct ethhdr *eh = (struct ethhdr *)buf; 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; /* 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 */ ip_write32h(alias_addr_ip, rah->ar_sip); /* target hw addr (none) */ memset(rah->ar_tha, 0, ETH_ALEN); /* target IP */ ip_write( iph->ip_dst, rah->ar_tip ); client_ip = 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); } }
void if_encap(const uint8_t *ip_data, int ip_data_len) { uint8_t buf[1600]; struct ethhdr *eh = (struct ethhdr *)buf; 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; 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); memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1); rah->ar_sha[5] = CTL_ALIAS; ip_write32h(alias_addr_ip, rah->ar_sip); memset(rah->ar_tha, 0, ETH_ALEN); ip_write( iph->ip_dst, rah->ar_tip ); client_ip = 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); 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); } }