Exemple #1
0
/**
 * Parse a READLINK reply
 *
 * @v readlink_reply    A structure where the data will be saved
 * @v reply             The ONC RPC reply to get data from
 * @ret rc              Return status code
 */
int nfs_get_readlink_reply ( struct nfs_readlink_reply *readlink_reply,
                             struct oncrpc_reply *reply ) {
	if ( ! readlink_reply || ! reply )
		return -EINVAL;

	readlink_reply->status = oncrpc_iob_get_int ( reply->data );
	switch ( readlink_reply->status )
	{
	case NFS3_OK:
		 break;
	case NFS3ERR_IO:
		return -EIO;
	case NFS3ERR_ACCES:
		return -EACCES;
	case NFS3ERR_INVAL:
		return -EINVAL;
	case NFS3ERR_NOTSUPP:
		return -ENOTSUP;
	case NFS3ERR_STALE:
		return -ESTALE;
	case NFS3ERR_BADHANDLE:
	case NFS3ERR_SERVERFAULT:
	default:
		return -EPROTO;
	}

	if ( oncrpc_iob_get_int ( reply->data ) == 1 )
		iob_pull ( reply->data, 5 * sizeof ( uint32_t ) +
		                        8 * sizeof ( uint64_t ) );

	readlink_reply->path_len = oncrpc_iob_get_int ( reply->data );
	readlink_reply->path     = reply->data->data;

	return 0;
}
Exemple #2
0
/**
 * Parse a READ reply
 *
 * @v read_reply        A structure where the data will be saved
 * @v reply             The ONC RPC reply to get data from
 * @ret rc              Return status code
 */
int nfs_get_read_reply ( struct nfs_read_reply *read_reply,
                         struct oncrpc_reply *reply ) {
	if ( ! read_reply || ! reply )
		return -EINVAL;

	read_reply->status = oncrpc_iob_get_int ( reply->data );
	switch ( read_reply->status )
	{
	case NFS3_OK:
		 break;
	case NFS3ERR_PERM:
		return -EPERM;
	case NFS3ERR_NOENT:
		return -ENOENT;
	case NFS3ERR_IO:
		return -EIO;
	case NFS3ERR_NXIO:
		return -ENXIO;
	case NFS3ERR_ACCES:
		return -EACCES;
	case NFS3ERR_INVAL:
		return -EINVAL;
	case NFS3ERR_STALE:
		return -ESTALE;
	case NFS3ERR_BADHANDLE:
	case NFS3ERR_SERVERFAULT:
	default:
		return -EPROTO;
	}

	if ( oncrpc_iob_get_int ( reply->data ) == 1 )
	{
		iob_pull ( reply->data, 5 * sizeof ( uint32_t ) );
		read_reply->filesize = oncrpc_iob_get_int64 ( reply->data );
		iob_pull ( reply->data, 7 * sizeof ( uint64_t ) );
	}

	read_reply->count    = oncrpc_iob_get_int ( reply->data );
	read_reply->eof      = oncrpc_iob_get_int ( reply->data );
	read_reply->data_len = oncrpc_iob_get_int ( reply->data );
	read_reply->data     = reply->data->data;

	if ( read_reply->count != read_reply->data_len )
		return -EPROTO;

	return 0;
}
Exemple #3
0
/**
 * Complete bulk IN transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void smsc95xx_in_complete ( struct usb_endpoint *ep,
				   struct io_buffer *iobuf, int rc ) {
	struct smsc95xx_device *smsc95xx =
		container_of ( ep, struct smsc95xx_device, usbnet.in );
	struct net_device *netdev = smsc95xx->netdev;
	struct smsc95xx_rx_header *header;

	/* Profile completions */
	profile_start ( &smsc95xx_in_profiler );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open ) {
		free_iob ( iobuf );
		return;
	}

	/* Record USB errors against the network device */
	if ( rc != 0 ) {
		DBGC ( smsc95xx, "SMSC95XX %p bulk IN failed: %s\n",
		       smsc95xx, strerror ( rc ) );
		goto err;
	}

	/* Sanity check */
	if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) {
		DBGC ( smsc95xx, "SMSC95XX %p underlength bulk IN\n",
		       smsc95xx );
		DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto err;
	}

	/* Strip header and CRC */
	header = iobuf->data;
	iob_pull ( iobuf, sizeof ( *header ) );
	iob_unput ( iobuf, 4 /* CRC */ );

	/* Check for errors */
	if ( header->command & cpu_to_le32 ( SMSC95XX_RX_RUNT |
					     SMSC95XX_RX_LATE |
					     SMSC95XX_RX_CRC ) ) {
		DBGC ( smsc95xx, "SMSC95XX %p receive error (%08x):\n",
		       smsc95xx, le32_to_cpu ( header->command ) );
		DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EIO;
		goto err;
	}

	/* Hand off to network stack */
	netdev_rx ( netdev, iob_disown ( iobuf ) );

	profile_stop ( &smsc95xx_in_profiler );
	return;

 err:
	/* Hand off to network stack */
	netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
}
Exemple #4
0
/**
 * Extract a file handle from the beginning of an I/O buffer
 *
 * @v io_buf            I/O buffer
 * @v fh                File handle
 * @ret size            Size of the data read
 */
size_t nfs_iob_get_fh ( struct io_buffer *io_buf, struct nfs_fh *fh ) {
	fh->size = oncrpc_iob_get_int ( io_buf );

	if ( fh->size > 64 )
		return sizeof ( uint32_t );

	memcpy (fh->fh, io_buf->data, fh->size );
	iob_pull ( io_buf, fh->size );

	return fh->size + sizeof ( uint32_t );
}
Exemple #5
0
static int legacy_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
    struct nic *nic = netdev->priv;
    struct ethhdr *ethhdr;

    DBG ( "Transmitting %zd bytes\n", iob_len ( iobuf ) );
    iob_pad ( iobuf, ETH_ZLEN );
    ethhdr = iobuf->data;
    iob_pull ( iobuf, sizeof ( *ethhdr ) );
    nic->nic_op->transmit ( nic, ( const char * ) ethhdr->h_dest,
                            ntohs ( ethhdr->h_protocol ),
                            iob_len ( iobuf ), iobuf->data );
    netdev_tx_complete ( netdev, iobuf );
    return 0;
}
Exemple #6
0
/**
 * Complete bulk IN transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void dm96xx_in_complete ( struct usb_endpoint *ep,
				 struct io_buffer *iobuf, int rc ) {
	struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
						      usbnet.in );
	struct net_device *netdev = dm96xx->netdev;
	struct dm96xx_rx_header *header;

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open ) {
		free_iob ( iobuf );
		return;
	}

	/* Record USB errors against the network device */
	if ( rc != 0 ) {
		DBGC ( dm96xx, "DM96XX %p bulk IN failed: %s\n",
		       dm96xx, strerror ( rc ) );
		goto err;
	}

	/* Sanity check */
	if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) {
		DBGC ( dm96xx, "DM96XX %p underlength bulk IN\n", dm96xx );
		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto err;
	}

	/* Strip header and CRC */
	header = iobuf->data;
	iob_pull ( iobuf, sizeof ( *header ) );
	iob_unput ( iobuf, 4 /* CRC */ );

	/* Check status */
	if ( header->rsr & ~DM96XX_RSR_MF ) {
		DBGC ( dm96xx, "DM96XX %p receive error %02x:\n",
		       dm96xx, header->rsr );
		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EIO;
		goto err;
	}

	/* Hand off to network stack */
	netdev_rx ( netdev, iob_disown ( iobuf ) );
	return;

 err:
	/* Hand off to network stack */
	netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
}
Exemple #7
0
static size_t gdbudp_recv ( char *buf, size_t len ) {
	struct io_buffer *iob;
	struct ethhdr *ethhdr;
	struct arphdr *arphdr;
	struct iphdr *iphdr;
	struct udp_header *udphdr;
	size_t payload_len;

	gdbudp_ensure_netdev_open ( netdev );

	for ( ; ; ) {
		netdev_poll ( netdev );
		while ( ( iob = netdev_rx_dequeue ( netdev ) ) != NULL ) {
			/* Ethernet header */
			if ( iob_len ( iob ) < sizeof ( *ethhdr ) ) {
				goto bad_packet;
			}
			ethhdr = iob->data;
			iob_pull ( iob, sizeof ( *ethhdr ) );

			/* Handle ARP requests so the client can find our MAC */
			if ( ethhdr->h_protocol == htons ( ETH_P_ARP ) ) {
				arphdr = iob->data;
				if ( iob_len ( iob ) < sizeof ( *arphdr ) + 2 * ( ETH_ALEN + sizeof ( struct in_addr ) ) ||
						arphdr->ar_hrd != htons ( ARPHRD_ETHER ) ||
						arphdr->ar_pro != htons ( ETH_P_IP ) ||
						arphdr->ar_hln != ETH_ALEN ||
						arphdr->ar_pln != sizeof ( struct in_addr ) ||
						arphdr->ar_op != htons ( ARPOP_REQUEST ) ||
						* ( uint32_t * ) arp_target_pa ( arphdr ) != source_addr.sin_addr.s_addr ) {
					goto bad_packet;
				}

				/* Generate an ARP reply */
				arphdr->ar_op = htons ( ARPOP_REPLY );
				memswap ( arp_sender_pa ( arphdr ), arp_target_pa ( arphdr ), sizeof ( struct in_addr ) );
				memcpy ( arp_target_ha ( arphdr ), arp_sender_ha ( arphdr ), ETH_ALEN );
				memcpy ( arp_sender_ha ( arphdr ), netdev->ll_addr, ETH_ALEN );

				/* Fix up ethernet header */
				ethhdr = iob_push ( iob, sizeof ( *ethhdr ) );
				memcpy ( ethhdr->h_dest, ethhdr->h_source, ETH_ALEN );
				memcpy ( ethhdr->h_source, netdev->ll_addr, ETH_ALEN );

				netdev_tx ( netdev, iob );
				continue; /* no need to free iob */
			}

			if ( ethhdr->h_protocol != htons ( ETH_P_IP ) ) {
				goto bad_packet;
			}

			/* IP header */
			if ( iob_len ( iob ) < sizeof ( *iphdr ) ) {
				goto bad_packet;
			}
			iphdr = iob->data;
			iob_pull ( iob, sizeof ( *iphdr ) );
			if ( iphdr->protocol != IP_UDP || iphdr->dest.s_addr != source_addr.sin_addr.s_addr ) {
				goto bad_packet;
			}

			/* UDP header */
			if ( iob_len ( iob ) < sizeof ( *udphdr ) ) {
				goto bad_packet;
			}
			udphdr = iob->data;
			if ( udphdr->dest != source_addr.sin_port ) {
				goto bad_packet;
			}

			/* Learn the remote connection details */
			memcpy ( dest_eth, ethhdr->h_source, ETH_ALEN );
			dest_addr.sin_addr.s_addr = iphdr->src.s_addr;
			dest_addr.sin_port = udphdr->src;

			/* Payload */
			payload_len = ntohs ( udphdr->len );
			if ( payload_len < sizeof ( *udphdr ) || payload_len > iob_len ( iob ) ) {
				goto bad_packet;
			}
			payload_len -= sizeof ( *udphdr );
			iob_pull ( iob, sizeof ( *udphdr ) );
			if ( payload_len > len ) {
				goto bad_packet;
			}
			memcpy ( buf, iob->data, payload_len );

			free_iob ( iob );
			return payload_len;

bad_packet:
			free_iob ( iob );
		}
		cpu_nap();
	}
}