Esempio n. 1
0
/*
 * Send a UDP packet.
 */
int
__udp_send(char *buf, int len, ip_route_t *dest_ip,
	   word dest_port, word src_port)
{
    pktbuf_t *pkt;
    udp_header_t *udp;
    ip_header_t *ip;
    unsigned short cksum;
    int ret;

    /* dumb */
    if (len > MAX_UDP_DATA)
	return -1;

    /* just drop it if can't get a buffer */
    if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL)
	return -1;

    udp = pkt->udp_hdr;
    ip = pkt->ip_hdr;

    pkt->pkt_bytes = len + sizeof(udp_header_t);

    udp->src_port = htons(src_port);
    udp->dest_port = htons(dest_port);
    udp->length = htons(pkt->pkt_bytes);
    udp->checksum = 0;

    memcpy(((char *)udp) + sizeof(udp_header_t), buf, len);

    /* fill in some pseudo-header fields */
    memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t));
    memcpy(ip->destination, dest_ip->ip_addr, sizeof(ip_addr_t));
    ip->protocol = IP_PROTO_UDP;
    ip->length = udp->length;

    cksum = __sum((word *)udp, pkt->pkt_bytes, __pseudo_sum(ip));
    udp->checksum = htons(cksum);

    ret = __ip_send(pkt, IP_PROTO_UDP, dest_ip);
    __pktbuf_free(pkt);
    return ret;
}
Esempio n. 2
0
static void do_ping(int argc, char *argv[])
{
	struct option_info opts[7];
	long count, timeout, length, rate, start_time, end_time, timer,
	    received, tries;
	char *local_ip_addr, *host_ip_addr;
	bool local_ip_addr_set, host_ip_addr_set, count_set,
	    timeout_set, length_set, rate_set, verbose;
	struct sockaddr_in local_addr, host_addr;
	ip_addr_t hold_addr;
	icmp_header_t *icmp;
	pktbuf_t *pkt;
	ip_header_t *ip;
	unsigned short cksum;
	ip_route_t dest_ip;

	init_opts(&opts[0], 'n', true, OPTION_ARG_TYPE_NUM,
		  (void *)&count, (bool *) & count_set,
		  "<count> - number of packets to test");
	init_opts(&opts[1], 't', true, OPTION_ARG_TYPE_NUM, (void *)&timeout,
		  (bool *) & timeout_set,
		  "<timeout> - max #ms per packet [rount trip]");
	init_opts(&opts[2], 'i', true, OPTION_ARG_TYPE_STR,
		  (void *)&local_ip_addr, (bool *) & local_ip_addr_set,
		  "local IP address");
	init_opts(&opts[3], 'h', true, OPTION_ARG_TYPE_STR,
		  (void *)&host_ip_addr, (bool *) & host_ip_addr_set,
		  "host name or IP address");
	init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM, (void *)&length,
		  (bool *) & length_set, "<length> - size of payload");
	init_opts(&opts[5], 'v', false, OPTION_ARG_TYPE_FLG, (void *)&verbose,
		  (bool *) 0, "verbose operation");
	init_opts(&opts[6], 'r', true, OPTION_ARG_TYPE_NUM, (void *)&rate,
		  (bool *) & rate_set, "<rate> - time between packets");
	if (!scan_opts(argc, argv, 1, opts, 7, (void **)0, 0, "")) {
		diag_printf("PING - Invalid option specified\n");
		return;
	}
	// Set defaults; this has to be done _after_ the scan, since it will
	// have destroyed all values not explicitly set.
	if (local_ip_addr_set) {
		if (!_gethostbyname(local_ip_addr, (in_addr_t *) & local_addr)) {
			diag_printf("PING - Invalid local name: %s\n",
				    local_ip_addr);
			return;
		}
	} else {
		memcpy((in_addr_t *) & local_addr, __local_ip_addr,
		       sizeof(__local_ip_addr));
	}
	if (host_ip_addr_set) {
		if (!_gethostbyname(host_ip_addr, (in_addr_t *) & host_addr)) {
			diag_printf("PING - Invalid host name: %s\n",
				    host_ip_addr);
			return;
		}
		if (__arp_lookup((ip_addr_t *) & host_addr.sin_addr, &dest_ip) <
		    0) {
			diag_printf("PING: Cannot reach server '%s' (%s)\n",
				    host_ip_addr,
				    inet_ntoa((in_addr_t *) & host_addr));
			return;
		}
	} else {
		diag_printf("PING - host name or IP address required\n");
		return;
	}
#define DEFAULT_LENGTH   64
#define DEFAULT_COUNT    10
#define DEFAULT_TIMEOUT  1000
#define DEFAULT_RATE     1000
	if (!rate_set) {
		rate = DEFAULT_RATE;
	}
	if (!length_set) {
		length = DEFAULT_LENGTH;
	}
	if ((length < 64) || (length > 1400)) {
		diag_printf("Invalid length specified: %ld\n", length);
		return;
	}
	if (!count_set) {
		count = DEFAULT_COUNT;
	}
	if (!timeout_set) {
		timeout = DEFAULT_TIMEOUT;
	}
	// Note: two prints here because 'inet_ntoa' returns a static pointer
	diag_printf("Network PING - from %s",
		    inet_ntoa((in_addr_t *) & local_addr));
	diag_printf(" to %s\n", inet_ntoa((in_addr_t *) & host_addr));
	received = 0;
	__icmp_install_listener(handle_icmp);
	// Save default "local" address
	memcpy(hold_addr, __local_ip_addr, sizeof(hold_addr));
	for (tries = 0; tries < count; tries++) {
		// The network stack uses the global variable '__local_ip_addr'
		memcpy(__local_ip_addr, &local_addr, sizeof(__local_ip_addr));
		// Build 'ping' request
		if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL) {
			// Give up if no packets - something is wrong
			break;
		}

		icmp = pkt->icmp_hdr;
		ip = pkt->ip_hdr;
		pkt->pkt_bytes = length + sizeof(icmp_header_t);

		icmp->type = ICMP_TYPE_ECHOREQUEST;
		icmp->code = 0;
		icmp->checksum = 0;
		icmp->seqnum = htons(tries + 1);
		cksum = __sum((word *) icmp, pkt->pkt_bytes, 0);
		icmp->checksum = htons(cksum);

		memcpy(ip->source, (in_addr_t *) & local_addr,
		       sizeof(ip_addr_t));
		memcpy(ip->destination, (in_addr_t *) & host_addr,
		       sizeof(ip_addr_t));
		ip->protocol = IP_PROTO_ICMP;
		ip->length = htons(pkt->pkt_bytes);

		__ip_send(pkt, IP_PROTO_ICMP, &dest_ip);
		__pktbuf_free(pkt);

		start_time = MS_TICKS();
		timer = start_time + timeout;
		icmp_received = false;
		while (!icmp_received && (MS_TICKS_DELAY() < timer)) {
			if (_rb_break(1)) {
				goto abort;
			}
			MS_TICKS_DELAY();
			__enet_poll();
		}
		end_time = MS_TICKS();

		timer = MS_TICKS() + rate;
		while (MS_TICKS_DELAY() < timer) {
			if (_rb_break(1)) {
				goto abort;
			}
			MS_TICKS_DELAY();
			__enet_poll();
		}

		if (icmp_received) {
			received++;
			if (verbose) {
				diag_printf(" seq: %ld, time: %ld (ticks)\n",
					    ntohs(hold_hdr.seqnum),
					    end_time - start_time);
			}
		}
	}
abort:
	__icmp_remove_listener();
	// Clean up
	memcpy(__local_ip_addr, &hold_addr, sizeof(__local_ip_addr));
	// Report
	diag_printf("PING - received %ld of %ld expected\n", received, count);
}
Esempio n. 3
0
/* 
 * Find the ethernet address of the machine with the given
 * ip address.
 * Return 0 and fills in 'eth_addr' if successful,
 *       -1 if unsuccessful.
 */
int
__arp_request(ip_addr_t *ip_addr, enet_addr_t *eth_addr, int allow_self)
{
    pktbuf_t *pkt;
    arp_header_t *arp;
    unsigned long retry_start;
    enet_addr_t   bcast_addr;
    int           retry;

    if (!allow_self) {
        // Special case request for self
        if (!memcmp(ip_addr, __local_ip_addr, 4)) {
            memcpy(eth_addr, __local_enet_addr, sizeof(enet_addr_t));
            return 0;
        }
    }

    /* just fail if can't get a buffer */
    if ((pkt = __pktbuf_alloc(ARP_PKT_SIZE)) == NULL)
	return -1;

    arp = pkt->arp_hdr;
    arp->opcode = htons(ARP_REQUEST);
    arp->hw_type = htons(ARP_HW_ETHER);
    arp->protocol = htons(0x800);
    arp->hw_len = sizeof(enet_addr_t);
    arp->proto_len = sizeof(ip_addr_t);

    memcpy(arp->sender_ip, __local_ip_addr, sizeof(ip_addr_t));
    memcpy(arp->sender_enet, __local_enet_addr, sizeof(enet_addr_t));
    memcpy(arp->target_ip, ip_addr, sizeof(ip_addr_t));

    bcast_addr[0] = 255;
    bcast_addr[1] = 255;
    bcast_addr[2] = 255;
    bcast_addr[3] = 255;
    bcast_addr[4] = 255;
    bcast_addr[5] = 255;

    arp_req.eth = (char *)eth_addr;
    arp_req.ip = (char *)ip_addr;
    arp_req.waiting = 1;

    retry = 8;
    while (retry-- > 0) {

        /* send the packet */
	pkt->pkt_bytes = sizeof(arp_header_t);
        __enet_send(pkt, &bcast_addr, ETH_TYPE_ARP);

        retry_start = MS_TICKS();
	while ((MS_TICKS_DELAY() - retry_start) < 250) {
	    __enet_poll();
	    if (!arp_req.waiting) {
		__pktbuf_free(pkt);
		return 0;
	    }
	}
    }
    __pktbuf_free(pkt);
    return -1;
}