Beispiel #1
0
static int af_packet_update_properties ( struct net_device *netdev )
{
	struct af_packet_nic *nic = netdev->priv;
	struct ifreq if_data;
	int ret;

	/* retrieve default MAC address */
	int fd = linux_socket(LINUX_AF_PACKET, LINUX_SOCK_RAW, 0);
	if (fd < 0) {
		DBGC(nic, "af_packet %p cannot create raw socket (%s)\n",
		     nic, linux_strerror(linux_errno));
		return fd;
	}

	/* retrieve host's MAC address */
	memset(&if_data, 0, sizeof(if_data));
	strncpy(if_data.ifr_name, nic->ifname, sizeof(if_data.ifr_name));
	ret = linux_ioctl(fd, LINUX_SIOCGIFHWADDR, &if_data);
	if (ret < 0) {
		DBGC(nic, "af_packet %p cannot get mac addr (%s)\n",
		     nic, linux_strerror(linux_errno));
		linux_close(fd);
		return ret;
	}

	linux_close(fd);
	/* struct sockaddr = { u16 family, u8 pad[14] (equiv. sa_data) }; */
	memcpy(netdev->ll_addr, if_data.ifr_hwaddr.pad, ETH_ALEN);
	return 0;
}
/**
 * Open PCI configuration space
 *
 * @v pci		PCI device
 * @v flags		Access mode flags
 * @v where		Address within configuration space
 * @ret fd		File handle, or negative error
 */
static int linux_pci_open ( struct pci_device *pci, int flags,
			    unsigned long where ) {
	char filename[ 22 /* "/proc/bus/pci/xx/xx.x" + NUL */ ];
	int fd;
	int rc;

	/* Construct filename */
	snprintf ( filename, sizeof ( filename ), "/proc/bus/pci/%02x/%02x.%x",
		   PCI_BUS ( pci->busdevfn ), PCI_SLOT ( pci->busdevfn ),
		   PCI_FUNC ( pci->busdevfn ) );

	/* Open file */
	fd = linux_open ( filename, flags );
	if ( fd < 0 ) {
		DBGC ( pci, "PCI could not open %s: %s\n", filename,
		       linux_strerror ( linux_errno ) );
		rc = -ELINUX ( linux_errno );
		goto err_open;
	}

	/* Seek to location */
	if ( linux_lseek ( fd, where, SEEK_SET ) < 0 ) {
		DBGC ( pci, "PCI could not seek to %s offset %#02lx: %s\n",
		       filename, where, linux_strerror ( linux_errno ) );
		rc = -ELINUX ( linux_errno );
		goto err_seek;
	}

	return fd;

 err_seek:
	linux_close ( fd );
 err_open:
	return rc;
}
Beispiel #3
0
/** Open the linux interface */
static int af_packet_nic_open ( struct net_device * netdev )
{
	struct af_packet_nic * nic = netdev->priv;
	struct sockaddr_ll socket_address;
	struct ifreq if_data;
	int ret;

	nic->fd = linux_socket(LINUX_AF_PACKET, LINUX_SOCK_RAW,
			       htons(ETH_P_ALL));
	if (nic->fd < 0) {
		DBGC(nic, "af_packet %p socket(AF_PACKET) = %d (%s)\n",
		     nic, nic->fd, linux_strerror(linux_errno));
		return nic->fd;
	}

	/* resolve ifindex of ifname */
	memset(&if_data, 0, sizeof(if_data));
	strncpy(if_data.ifr_name, nic->ifname, sizeof(if_data.ifr_name));
	ret = linux_ioctl(nic->fd, LINUX_SIOCGIFINDEX, &if_data);
	if (ret < 0) {
		DBGC(nic, "af_packet %p ioctl(SIOCGIFINDEX) = %d (%s)\n",
		     nic, ret, linux_strerror(linux_errno));
		linux_close(nic->fd);
		return ret;
	}

	nic->ifindex = if_data.ifr_ifindex;

	/* bind to interface */
	memset(&socket_address, 0, sizeof(socket_address));
	socket_address.sll_family = LINUX_AF_PACKET;
	socket_address.sll_ifindex = nic->ifindex;
	socket_address.sll_protocol = htons(ETH_P_ALL);
	ret = linux_bind(nic->fd, (void *) &socket_address,
			 sizeof(socket_address));
	if (ret == -1) {
		DBGC(nic, "af_packet %p bind() = %d (%s)\n",
		     nic, ret, linux_strerror(linux_errno));
		linux_close(nic->fd);
		return ret;
	}

	/* Set nonblocking mode to make af_packet_nic_poll() easier */
	ret = linux_fcntl(nic->fd, F_SETFL, O_NONBLOCK);
	if (ret != 0) {
		DBGC(nic, "af_packet %p fcntl(%d, ...) = %d (%s)\n",
		     nic, nic->fd, ret, linux_strerror(linux_errno));
		linux_close(nic->fd);
		return ret;
	}

	return 0;
}
Beispiel #4
0
/** Setup the terminal for our use */
static void linux_console_startup(void)
{
	struct termios t;

	if (linux_tcgetattr(0, &t)) {
		DBG("linux_console tcgetattr failed (%s)", linux_strerror(linux_errno));
		return;
	}

	saved_termios = t;

	/* Disable canonical mode and echo. Let readline handle that */
	t.c_lflag &= ~(ECHO | ICANON);
	/* stop ^C from sending a signal */
	t.c_cc[VINTR] = 0;

	if (linux_tcsetattr(0, TCSAFLUSH, &t))
		DBG("linux_console tcsetattr failed (%s)", linux_strerror(linux_errno));
}
/**
 * Get noise sample
 *
 * @ret noise		Noise sample
 * @ret rc		Return status code
 */
static int linux_get_noise ( noise_sample_t *noise ) {
	uint8_t byte;
	ssize_t len;

	/* Read a single byte from entropy source */
	len = linux_read ( entropy_fd, &byte, sizeof ( byte ) );
	if ( len < 0 ) {
		DBGC ( &entropy_fd, "ENTROPY could not read from %s: %s\n",
		       entropy_filename, linux_strerror ( linux_errno ) );
		return len;
	}
	if ( len == 0 ) {
		DBGC ( &entropy_fd, "ENTROPY EOF on reading from %s: %s\n",
		       entropy_filename, linux_strerror ( linux_errno ) );
		return -EPIPE;
	}
	*noise = byte;

	return 0;
}
/**
 * Enable entropy gathering
 *
 * @ret rc		Return status code
 */
static int linux_entropy_enable ( void ) {

	/* Open entropy source */
	entropy_fd = linux_open ( entropy_filename, O_RDONLY );
	if ( entropy_fd < 0 ) {
		DBGC ( &entropy_fd, "ENTROPY could not open %s: %s\n",
		       entropy_filename, linux_strerror ( linux_errno ) );
		return entropy_fd;
	}

	return 0;
}
Beispiel #7
0
static int linux_console_getchar()
{
	char c;

	/* read from stdin */
	if (linux_read(0, &c, 1) < 0) {
		DBG("linux_console read failed (%s)\n", linux_strerror(linux_errno));
		return 0;
	}
	/* backspace seems to be returned as ascii del, map it here */
	if (c == 0x7f)
		return KEY_BACKSPACE;
	else
		return c;
}
Beispiel #8
0
static int linux_console_iskey()
{
	struct pollfd pfd;
	pfd.fd = 0;
	pfd.events = POLLIN;

	/* poll for data to be read on stdin */
	if (linux_poll(&pfd, 1, 0) == -1) {
		DBG("linux_console poll failed (%s)\n", linux_strerror(linux_errno));
		return 0;
	}

	if (pfd.revents & POLLIN)
		return 1;
	else
		return 0;
}
/**
 * Read from PCI configuration space
 *
 * @v pci		PCI device
 * @v where		Address within configuration space
 * @v value		Data buffer
 * @v len		Length to read
 * @ret rc		Return status code
 */
int linux_pci_read ( struct pci_device *pci, unsigned long where,
		     unsigned long *value, size_t len ) {
	uint32_t tmp = 0;
	int fd;
	int check_len;
	int rc;

	/* Return "missing device" in case of error */
	*value = -1UL;

	/* Open configuration space */
	fd = linux_pci_open ( pci, O_RDONLY, where );
	if ( fd < 0 ) {
		rc = fd;
		goto err_open;
	}

	/* Read value */
	check_len = linux_read ( fd, &tmp, len );
	if ( check_len < 0 ) {
		DBGC ( pci, "PCI could not read from " PCI_FMT " %#02lx+%#zx: "
		       "%s\n", PCI_ARGS ( pci ), where, len,
		       linux_strerror ( linux_errno ) );
		rc = -ELINUX ( linux_errno );
		goto err_read;
	}
	if ( ( size_t ) check_len != len ) {
		DBGC ( pci, "PCI read only %#x bytes from " PCI_FMT
		       " %#02lx+%#zx\n", check_len, PCI_ARGS ( pci ),
		       where, len );
		rc = -EIO;
		goto err_read;
	}

	/* Return value */
	*value = le32_to_cpu ( tmp );

	/* Success */
	rc = 0;

 err_read:
	linux_close ( fd );
 err_open:
	return rc;
}
/**
 * Write to PCI configuration space
 *
 * @v pci		PCI device
 * @v where		Address within configuration space
 * @v value		Value to write
 * @v len		Length of value
 * @ret rc		Return status code
 */
int linux_pci_write ( struct pci_device *pci, unsigned long where,
		      unsigned long value, size_t len ) {
	uint32_t tmp;
	int fd;
	int check_len;
	int rc;

	/* Open configuration space */
	fd = linux_pci_open ( pci, O_WRONLY, where );
	if ( fd < 0 ) {
		rc = fd;
		goto err_open;
	}

	/* Prepare value for writing */
	tmp = cpu_to_le32 ( value );
	assert ( len <= sizeof ( tmp ) );

	/* Write value */
	check_len = linux_write ( fd, &tmp, len );
	if ( check_len < 0 ) {
		DBGC ( pci, "PCI could not write to " PCI_FMT " %#02lx+%#zx: "
		       "%s\n", PCI_ARGS ( pci ), where, len,
		       linux_strerror ( linux_errno ) );
		rc = -ELINUX ( linux_errno );
		goto err_write;
	}
	if ( ( size_t ) check_len != len ) {
		DBGC ( pci, "PCI wrote only %#x bytes to " PCI_FMT
		       " %#02lx+%#zx\n", check_len, PCI_ARGS ( pci ),
		       where, len );
		rc = -EIO;
		goto err_write;
	}

	/* Success */
	rc = 0;

 err_write:
	linux_close ( fd );
 err_open:
	return rc;
}
Beispiel #11
0
/** Poll for new packets */
static void af_packet_nic_poll ( struct net_device *netdev )
{
	struct af_packet_nic * nic = netdev->priv;
	struct pollfd pfd;
	struct io_buffer * iobuf;
	int r;

	pfd.fd = nic->fd;
	pfd.events = POLLIN;
	if (linux_poll(&pfd, 1, 0) == -1) {
		DBGC(nic, "af_packet %p poll failed (%s)\n",
		     nic, linux_strerror(linux_errno));
		return;
	}
	if ((pfd.revents & POLLIN) == 0)
		return;

	/* At this point we know there is at least one new packet to be read */

	iobuf = alloc_iob(RX_BUF_SIZE);
	if (! iobuf)
		goto allocfail;

	while ((r = linux_read(nic->fd, iobuf->data, RX_BUF_SIZE)) > 0) {
		DBGC2(nic, "af_packet %p read %d bytes\n", nic, r);

		iob_put(iobuf, r);
		netdev_rx(netdev, iobuf);

		iobuf = alloc_iob(RX_BUF_SIZE);
		if (! iobuf)
			goto allocfail;
	}

	free_iob(iobuf);
	return;

allocfail:
	DBGC(nic, "af_packet %p alloc_iob failed\n", nic);
}
Beispiel #12
0
static void linux_console_putchar(int c)
{
	/* write to stdout */
	if (linux_write(1, &c, 1) != 1)
		DBG("linux_console write failed (%s)\n", linux_strerror(linux_errno));
}
Beispiel #13
0
/** Restores original terminal attributes on shutdown */
static void linux_console_shutdown(int flags __unused)
{
	if (linux_tcsetattr(0, TCSAFLUSH, &saved_termios))
		DBG("linux_console tcsetattr failed (%s)", linux_strerror(linux_errno));
}