示例#1
0
static int
st_recv(void)
{
	char *tmp;
	char *buf;
	int buf_len, ret;

	if (g_sock_fd == NO_OPENED_SOCKET) {
		printf("! No socket opened\n");
		return (-1);
	}

	if ((tmp = strtok(NULL, " ")) == NULL) {
		printf("! No buffer len given\n");
		return (-1);
	}
	buf_len = atoi(tmp);

	if ((buf = bkmem_zalloc(buf_len)) == NULL) {
		printf("! Cannot allocate buffer: %d\n", errno);
		return (-1);
	}
	if ((ret = st_local_recv(g_sock_fd, buf, buf_len, 0)) <= 0) {
		if (ret == 0) {
			printf("@ EOF received: %d\n", errno);
			return (0);
		}
		printf("! Cannot recv: %d\n", errno);
		return (-1);
	}
	printf("@ Bytes received: %d\n", ret);
	hexdump(buf, ret);
	bkmem_free(buf, buf_len);
	return (0);
}
示例#2
0
static int
st_recvfrom(void)
{
	char *tmp;
	char *buf;
	int buf_len, ret;
	struct sockaddr_in from;
	socklen_t fromlen;

	if (g_sock_fd == NO_OPENED_SOCKET) {
		printf("! No socket opened\n");
		return (-1);
	}

	if ((tmp = strtok(NULL, " ")) == NULL) {
		printf("! No buffer len given\n");
		return (-1);
	}
	buf_len = atoi(tmp);

	if ((buf = bkmem_zalloc(buf_len)) == NULL) {
		printf("! Cannot allocate buffer: %d\n", errno);
		return (-1);
	}
	fromlen = sizeof (from);
	if ((ret = st_local_recvfrom(g_sock_fd, buf, buf_len, 0,
	    (struct sockaddr *)&from, &fromlen)) <= 0) {
		if (ret == 0) {
			printf("@ EOF received: %d\n", errno);
			return (0);
		}
		printf("! Cannot recv: %d\n", errno);
		return (-1);
	}
	printf("@ Bytes received from %s/%d: %d\n",
	    inet_ntoa(from.sin_addr), ntohs(from.sin_port), ret);
	hexdump(buf, ret);
	bkmem_free(buf, buf_len);
	return (0);
}
示例#3
0
/*
 * To act as an echo server.  Note that it assumes the address and
 * netmask have been set.
 */
static int
st_echo(void)
{
	char *tmp;
	int listen_fd, newfd;
	int echo_port;
	struct sockaddr_in addr;
	socklen_t addr_size;
	int backlog = 20;
	char *buf;
	int buf_len, ret, snd_cnt;

	tmp = strtok(NULL, " ");
	if (tmp == NULL) {
		printf("! No echo port given\n");
		return (-1);
	}
	echo_port = atoi(tmp);
	tmp = strtok(NULL, " ");
	if (tmp == NULL) {
		printf("! No buffer size given\n");
		return (-1);
	}
	buf_len = atoi(tmp);

	/* Create local socket for echo server */
	if ((listen_fd = st_local_socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		printf("! Error in opening TCP socket: %d\n", errno);
		return (-1);
	} else {
		printf("@ Local TCP socket opened\n");
	}

	/* Bind local socket */
	addr.sin_family = AF_INET;
	addr.sin_port = htons(echo_port);
	addr.sin_addr.s_addr = INADDR_ANY;

	if (st_local_bind(listen_fd, (struct sockaddr *)&addr,
	    sizeof (addr)) < 0) {
		printf("! Bind failed: %d\n", errno);
		return (-1);
	}
	if (st_local_listen(listen_fd, backlog) < 0) {
		printf("! Listen failed: %d\n", errno);
		return (-1);
	}

	addr_size = sizeof (addr);
	if ((newfd = st_local_accept(listen_fd, (struct sockaddr *)&addr,
	    &addr_size)) < 0) {
		printf("! Accept failed: %d\n", errno);
		(void) st_local_socket_close(listen_fd);
		return (-1);
	}
	printf("@ Accepted connection: %s/%d\n", inet_ntoa(addr.sin_addr),
		ntohs(addr.sin_port));
	(void) st_local_socket_close(listen_fd);

	if ((buf = bkmem_zalloc(buf_len)) == NULL) {
		printf("! Cannot allocate buffer: %d\n", errno);
		(void) st_local_socket_close(newfd);
		return (-1);
	}
	while ((ret = st_local_recv(newfd, buf, buf_len, 0)) > 0) {
		printf("@ Bytes received: %d\n", ret);
		hexdump(buf, ret);
		if ((snd_cnt = st_local_send(newfd, buf, ret, 0)) < ret) {
			printf("! Send failed: %d\n", errno);
			bkmem_free(buf, buf_len);
			return (-1);
		}
		printf("@ Sent %d bytes\n", snd_cnt);
	}
	(void) st_local_socket_close(newfd);
	if (ret < 0) {
		printf("! Cannot recv: %d\n", errno);
		bkmem_free(buf, buf_len);
		return (-1);
	} else {
		return (0);
	}
}
示例#4
0
/*
 * Handle a IP datagram addressed to our MAC address or to the link
 * layer broadcast address. Also respond to ARP requests. Generates
 * inetgrams as long as there's data and the mac level IP timeout timer
 * hasn't expired. As soon as there is no data, we try for
 * IBD_INPUT_ATTEMPTS for more, then exit the loop, even if there is time
 * left, since we expect to have data waiting for us when we're called, we just
 * don't know how much.
 *
 * We workaround slow proms (some proms have hard sleeps for as much as 3msec)
 * even though there are is data waiting.
 *
 * Returns the total number of MEDIA_LVL frames placed on the socket.
 * Caller is expected to free up the inetgram resources.
 */
static int
ibd_input(int index)
{
	struct inetgram		*inp;
	ipoib_ptxhdr_t		*eh;
	int		frames = 0;	/* successful frames */
	int		attempts = 0;	/* failed attempts after success */
	int16_t		len = 0, data_len;
	uint32_t	timeout, reltime;
	uint32_t	pre_pr, post_pr; /* prom_read interval */

#ifdef	DEBUG
	int		failures = 0;		/* total failures */
	int		total_attempts = 0;	/* total prom_read */
	int		no_data = 0;		/* no data in prom */
	int		arps = 0;		/* arp requests processed */
	uint32_t	tot_pr = 0;		/* prom_read time */
	uint32_t	tot_pc = 0;		/* inetgram creation time */
	uint32_t	pre_pc;
	uint32_t	now;
#endif	/* DEBUG */

	if (!initialized)
		prom_panic("IPoIB device is not initialized.");

	if ((reltime = sockets[index].in_timeout) == 0)
		reltime = mac_state.mac_in_timeout;
	timeout = prom_gettime() + reltime;

	do {
		if (frames > IBD_MAX_FRAMES) {
			/* someone is trying a denial of service attack */
			break;
		}

		/*
		 * The following is being paranoid about possible bugs
		 * where prom_read() returns a nonzero length, even when
		 * it's not read a packet; it zeroes out the header to
		 * compensate. Paranoia from calvin prom (V2) days.
		 */
		bzero(mac_state.mac_buf, sizeof (ipoib_ptxhdr_t));

		/*
		 * Prom_read() will return 0 or -2 if no data is present. A
		 * return value of -1 means an error has occurred. We adjust
		 * the timeout by calling the time spent in prom_read() "free".
		 * prom_read() returns the number of bytes actually read, but
		 * will only copy "len" bytes into our buffer. Adjust in
		 * case the MTU is wrong.
		 */
		pre_pr = prom_gettime();
		len = prom_read(mac_state.mac_dev, mac_state.mac_buf,
		    mac_state.mac_mtu, 0, NETWORK);
		post_pr = prom_gettime();
		timeout += (post_pr - pre_pr);
#ifdef	DEBUG
		tot_pr += (post_pr - pre_pr);
		total_attempts++;
#endif	/* DEBUG */

		if (len > mac_state.mac_mtu) {
			dprintf("ibd_input: adjusting MTU %d -> %d\n",
			    mac_state.mac_mtu, len);
			bkmem_free(mac_state.mac_buf, mac_state.mac_mtu);
			mac_state.mac_mtu = len;
			mac_state.mac_buf = bkmem_alloc(mac_state.mac_mtu);
			if (mac_state.mac_buf == NULL) {
				prom_panic("ibd_input: Cannot reallocate "
				    "netbuf memory.");
			}
			len = 0; /* pretend there was no data */
		}

		if (len == -1) {
#ifdef	DEBUG
			failures++;
#endif	/* DEBUG */
			break;
		}
		if (len == 0 || len == -2) {
			if (frames != 0)
				attempts++;
#ifdef	DEBUG
			no_data++;
#endif	/* DEBUG */
			continue;
		}

		eh = (ipoib_ptxhdr_t *)mac_state.mac_buf;
		if (eh->ipoib_rhdr.ipoib_type == ntohs(ETHERTYPE_IP) &&
		    len >= (sizeof (ipoib_ptxhdr_t) + sizeof (struct ip))) {

			int offset;
#ifdef	DEBUG
			pre_pc = prom_gettime();
#endif	/* DEBUG */

			inp = (struct inetgram *)bkmem_zalloc(
			    sizeof (struct inetgram));
			if (inp == NULL) {
				errno = ENOMEM;
				return (frames == 0 ? -1 : frames);
			}
			offset = sizeof (ipoib_ptxhdr_t);
			data_len = len - offset;
			inp->igm_mp = allocb(data_len, 0);
			if (inp->igm_mp == NULL) {
				errno = ENOMEM;
				bkmem_free((caddr_t)inp,
				    sizeof (struct inetgram));
				return (frames == 0 ? -1 : frames);
			}
			bcopy((caddr_t)(mac_state.mac_buf + offset),
			    inp->igm_mp->b_rptr, data_len);
			inp->igm_mp->b_wptr += data_len;
			inp->igm_level = NETWORK_LVL;
			add_grams(&sockets[index].inq, inp);
			frames++;
			attempts = 0;
#ifdef	DEBUG
			tot_pc += prom_gettime() - pre_pc;
#endif	/* DEBUG */
			continue;
		}

		if (eh->ipoib_rhdr.ipoib_type == ntohs(ETHERTYPE_ARP) &&
		    len >= sizeof (struct arp_packet)) {

			struct in_addr		ip;
			struct ibd_arp		*ea;

#ifdef	DEBUG
			printf("ibd_input: ARP message received\n");
			arps++;
#endif	/* DEBUG */

			ea = (struct ibd_arp *)(mac_state.mac_buf +
			    sizeof (ipoib_ptxhdr_t));
			if (ea->arp_pro != ntohs(ETHERTYPE_IP))
				continue;

			ipv4_getipaddr(&ip);
			ip.s_addr = ntohl(ip.s_addr);

			if (ea->arp_op == ntohs(ARPOP_REQUEST) &&
			    ip.s_addr != INADDR_ANY &&
			    (bcmp((caddr_t)ea->arp_tpa, (caddr_t)&ip,
			    sizeof (struct in_addr)) == 0)) {
				ea->arp_op = htons(ARPOP_REPLY);
				bcopy((caddr_t)&ea->arp_sha,
				    (caddr_t)&eh->ipoib_dest, IPOIB_ADDRL);
				bcopy((caddr_t)&ea->arp_sha,
				    (caddr_t)&ea->arp_tha, IPOIB_ADDRL);
				bcopy((caddr_t)ea->arp_spa,
				    (caddr_t)ea->arp_tpa,
				    sizeof (struct in_addr));
				bcopy(mac_state.mac_addr_buf,
				    (caddr_t)&ea->arp_sha,
				    mac_state.mac_addr_len);
				bcopy((caddr_t)&ip, (caddr_t)ea->arp_spa,
				    sizeof (struct in_addr));
				(void) prom_write(mac_state.mac_dev,
				    mac_state.mac_buf,
				    sizeof (struct arp_packet), 0, NETWORK);
				/* don't charge for ARP replies */
				timeout += reltime;
			}
		}
	} while (attempts < IBD_INPUT_ATTEMPTS &&
#ifdef	DEBUG
	    (now = prom_gettime()) < timeout);
#else
	    prom_gettime() < timeout);
#endif	/* DEBUG */

#ifdef	DEBUG
	printf("ibd_input(%d): T/S/N/A/F/P/M: %d/%d/%d/%d/%d/%d/%d "
	    "T/O: %d < %d = %s\n", index, total_attempts, frames, no_data,
	    arps, failures, tot_pr, tot_pc, now, timeout,
	    (now < timeout) ? "TRUE" : "FALSE");
#endif	/* DEBUG */
	return (frames);
}