Esempio n. 1
0
void arp_raw_request(struct in_addr source_ip, const uchar *target_ethaddr,
	struct in_addr target_ip)
{
	uchar *pkt;
	struct arp_hdr *arp;
	int eth_hdr_size;

	debug_cond(DEBUG_DEV_PKT, "ARP broadcast %d\n", arp_wait_try);

	pkt = arp_tx_packet;

	eth_hdr_size = net_set_ether(pkt, net_bcast_ethaddr, PROT_ARP);
	pkt += eth_hdr_size;

	arp = (struct arp_hdr *)pkt;

	arp->ar_hrd = htons(ARP_ETHER);
	arp->ar_pro = htons(PROT_IP);
	arp->ar_hln = ARP_HLEN;
	arp->ar_pln = ARP_PLEN;
	arp->ar_op = htons(ARPOP_REQUEST);

	memcpy(&arp->ar_sha, net_ethaddr, ARP_HLEN);	/* source ET addr */
	net_write_ip(&arp->ar_spa, source_ip);		/* source IP addr */
	memcpy(&arp->ar_tha, target_ethaddr, ARP_HLEN);	/* target ET addr */
	net_write_ip(&arp->ar_tpa, target_ip);		/* target IP addr */

	net_send_packet(arp_tx_packet, eth_hdr_size + ARP_HDR_SIZE);
}
Esempio n. 2
0
static int sb_eth_raw_recv(struct udevice *dev, int flags, uchar **packetp)
{
	struct eth_pdata *pdata = dev_get_platdata(dev);
	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
	int retval = 0;
	int length;

	if (reply_arp) {
		struct arp_hdr *arp = (void *)net_rx_packets[0] +
			ETHER_HDR_SIZE;

		/*
		 * Fake an ARP response. The u-boot network stack is sending an
		 * ARP request (to find the MAC address to address the actual
		 * packet to) and requires an ARP response to continue. Since
		 * this is the localhost interface, there is no Etherent level
		 * traffic at all, so there is no way to send an ARP request or
		 * to get a response. For this reason we fake the response to
		 * make the u-boot network stack happy.
		 */
		arp->ar_hrd = htons(ARP_ETHER);
		arp->ar_pro = htons(PROT_IP);
		arp->ar_hln = ARP_HLEN;
		arp->ar_pln = ARP_PLEN;
		arp->ar_op = htons(ARPOP_REPLY);
		/* Any non-zero MAC address will work */
		memset(&arp->ar_sha, 0x01, ARP_HLEN);
		/* Use whatever IP we were looking for (always 127.0.0.1?) */
		net_write_ip(&arp->ar_spa, arp_ip);
		memcpy(&arp->ar_tha, pdata->enetaddr, ARP_HLEN);
		net_write_ip(&arp->ar_tpa, net_ip);
		length = ARP_HDR_SIZE;
	} else {
		/* If local, the Ethernet header won't be included; skip it */
		uchar *pktptr = priv->local ?
			net_rx_packets[0] + ETHER_HDR_SIZE : net_rx_packets[0];

		retval = sandbox_eth_raw_os_recv(pktptr, &length, priv);
	}

	if (!retval && length) {
		if (priv->local) {
			struct ethernet_hdr *eth = (void *)net_rx_packets[0];

			/* Fill in enough of the missing Ethernet header */
			memcpy(eth->et_dest, pdata->enetaddr, ARP_HLEN);
			memset(eth->et_src, 0x01, ARP_HLEN);
			eth->et_protlen = htons(reply_arp ? PROT_ARP : PROT_IP);
			reply_arp = 0;
			length += ETHER_HDR_SIZE;
		}

		debug("eth_sandbox_raw: received packet %d\n",
		      length);
		*packetp = net_rx_packets[0];
		return length;
	}
	return retval;
}
Esempio n. 3
0
static int bootp_request(void)
{
	struct bootp *bp;
	int ext_len;
	int ret;
	unsigned char *payload = net_udp_get_payload(dhcp_con);
	const char *bfile;

	dhcp_state = INIT;

	debug("BOOTP broadcast\n");

	bp = (struct bootp *)payload;
	bp->bp_op = OP_BOOTREQUEST;
	bp->bp_htype = HWT_ETHER;
	bp->bp_hlen = HWL_ETHER;
	bp->bp_hops = 0;
	bp->bp_secs = htons(get_time_ns() >> 30);
	net_write_ip(&bp->bp_ciaddr, 0);
	net_write_ip(&bp->bp_yiaddr, 0);
	net_write_ip(&bp->bp_siaddr, 0);
	net_write_ip(&bp->bp_giaddr, 0);
	memcpy(bp->bp_chaddr, dhcp_con->et->et_src, 6);

	bfile = getenv("bootfile");
	if (bfile)
		safe_strncpy (bp->bp_file, bfile, sizeof(bp->bp_file));

	/* Request additional information from the BOOTP/DHCP server */
	ext_len = dhcp_extended((u8 *)bp->bp_vend, DHCP_DISCOVER, 0, 0);

	Bootp_id = (uint32_t)get_time_ns();
	net_copy_uint32(&bp->bp_id, &Bootp_id);

	dhcp_state = SELECTING;

	ret = net_udp_send(dhcp_con, sizeof(*bp) + ext_len);

	return ret;
}
Esempio n. 4
0
static void dhcp_send_request_packet(struct bootp *bp_offer)
{
	struct bootp *bp;
	int extlen;
	IPaddr_t OfferedIP;
	unsigned char *payload = net_udp_get_payload(dhcp_con);

	debug("%s: Sending DHCPREQUEST\n", __func__);

	bp = (struct bootp *)payload;
	bp->bp_op = OP_BOOTREQUEST;
	bp->bp_htype = HWT_ETHER;
	bp->bp_hlen = HWL_ETHER;
	bp->bp_hops = 0;
	/* FIXME what is this? */
//	bp->bp_secs = htons(get_timer(0) / CFG_HZ);
	net_copy_ip(&bp->bp_ciaddr, &bp_offer->bp_ciaddr); /* both in network byte order */
	net_copy_ip(&bp->bp_yiaddr, &bp_offer->bp_yiaddr);
	net_copy_ip(&bp->bp_siaddr, &bp_offer->bp_siaddr);
	/*
	 * RFC3046 requires Relay Agents to discard packets with
	 * nonzero and offered giaddr
	 */
	net_write_ip(&bp->bp_giaddr, 0);

	memcpy(bp->bp_chaddr, dhcp_con->et->et_src, 6);

	/*
	 * ID is the id of the OFFER packet
	 */

	net_copy_uint32(&bp->bp_id, &bp_offer->bp_id);

	/*
	 * Copy options from OFFER packet if present
	 */
	net_copy_ip(&OfferedIP, &bp->bp_yiaddr);
	extlen = dhcp_extended((u8 *)bp->bp_vend, DHCP_REQUEST, net_dhcp_server_ip,
				OfferedIP);

	debug("Transmitting DHCPREQUEST packet\n");
	net_udp_send(dhcp_con, sizeof(*bp) + extlen);
}
Esempio n. 5
0
static int sb_eth_send(struct udevice *dev, void *packet, int length)
{
	struct eth_sandbox_priv *priv = dev_get_priv(dev);
	struct ethernet_hdr *eth = packet;

	debug("eth_sandbox: Send packet %d\n", length);

	if (dev->seq >= 0 && dev->seq < ARRAY_SIZE(disabled) &&
	    disabled[dev->seq])
		return 0;

	if (ntohs(eth->et_protlen) == PROT_ARP) {
		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;

		if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
			struct ethernet_hdr *eth_recv;
			struct arp_hdr *arp_recv;

			/* store this as the assumed IP of the fake host */
			priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa);
			/* Formulate a fake response */
			eth_recv = (void *)priv->recv_packet_buffer;
			memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
			memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
			       ARP_HLEN);
			eth_recv->et_protlen = htons(PROT_ARP);

			arp_recv = (void *)priv->recv_packet_buffer +
				ETHER_HDR_SIZE;
			arp_recv->ar_hrd = htons(ARP_ETHER);
			arp_recv->ar_pro = htons(PROT_IP);
			arp_recv->ar_hln = ARP_HLEN;
			arp_recv->ar_pln = ARP_PLEN;
			arp_recv->ar_op = htons(ARPOP_REPLY);
			memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr,
			       ARP_HLEN);
			net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr);
			memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
			net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa);

			priv->recv_packet_length = ETHER_HDR_SIZE +
				ARP_HDR_SIZE;
		}
	} else if (ntohs(eth->et_protlen) == PROT_IP) {
		struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;

		if (ip->ip_p == IPPROTO_ICMP) {
			struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src;

			if (icmp->type == ICMP_ECHO_REQUEST) {
				struct ethernet_hdr *eth_recv;
				struct ip_udp_hdr *ipr;
				struct icmp_hdr *icmpr;

				/* reply to the ping */
				memcpy(priv->recv_packet_buffer, packet,
				       length);
				eth_recv = (void *)priv->recv_packet_buffer;
				ipr = (void *)priv->recv_packet_buffer +
					ETHER_HDR_SIZE;
				icmpr = (struct icmp_hdr *)&ipr->udp_src;
				memcpy(eth_recv->et_dest, eth->et_src,
				       ARP_HLEN);
				memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
				       ARP_HLEN);
				ipr->ip_sum = 0;
				ipr->ip_off = 0;
				net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src);
				net_write_ip((void *)&ipr->ip_src,
					     priv->fake_host_ipaddr);
				ipr->ip_sum = compute_ip_checksum(ipr,
					IP_HDR_SIZE);

				icmpr->type = ICMP_ECHO_REPLY;
				icmpr->checksum = 0;
				icmpr->checksum = compute_ip_checksum(icmpr,
					ICMP_HDR_SIZE);

				priv->recv_packet_length = length;
			}
		}
	}

	return 0;
}