/** * Transmit SRP SCSI command * * @v srp SRP device */ static void srp_cmd ( struct srp_device *srp ) { struct io_buffer *iobuf; struct srp_cmd *cmd; struct srp_memory_descriptor *data_out; struct srp_memory_descriptor *data_in; int rc; assert ( srp->state & SRP_STATE_LOGGED_IN ); /* Allocate I/O buffer */ iobuf = xfer_alloc_iob ( &srp->socket, SRP_MAX_I_T_IU_LEN ); if ( ! iobuf ) { rc = -ENOMEM; goto err; } /* Construct base portion */ cmd = iob_put ( iobuf, sizeof ( *cmd ) ); memset ( cmd, 0, sizeof ( *cmd ) ); cmd->type = SRP_CMD; cmd->tag.dwords[1] = htonl ( ++srp_tag ); cmd->lun = srp->lun; memcpy ( &cmd->cdb, &srp->command->cdb, sizeof ( cmd->cdb ) ); /* Construct data-out descriptor, if present */ if ( srp->command->data_out ) { cmd->data_buffer_formats |= SRP_CMD_DO_FMT_DIRECT; data_out = iob_put ( iobuf, sizeof ( *data_out ) ); data_out->address = cpu_to_be64 ( user_to_phys ( srp->command->data_out, 0 ) ); data_out->handle = ntohl ( srp->memory_handle ); data_out->len = ntohl ( srp->command->data_out_len ); } /* Construct data-in descriptor, if present */ if ( srp->command->data_in ) { cmd->data_buffer_formats |= SRP_CMD_DI_FMT_DIRECT; data_in = iob_put ( iobuf, sizeof ( *data_in ) ); data_in->address = cpu_to_be64 ( user_to_phys ( srp->command->data_in, 0 ) ); data_in->handle = ntohl ( srp->memory_handle ); data_in->len = ntohl ( srp->command->data_in_len ); } DBGC2 ( srp, "SRP %p TX SCSI command tag %08x%08x\n", srp, ntohl ( cmd->tag.dwords[0] ), ntohl ( cmd->tag.dwords[1] ) ); DBGC2_HDA ( srp, 0, iobuf->data, iob_len ( iobuf ) ); /* Send IU */ if ( ( rc = xfer_deliver_iob ( &srp->socket, iobuf ) ) != 0 ) { DBGC ( srp, "SRP %p could not send command: %s\n", srp, strerror ( rc ) ); goto err; } return; err: srp_fail ( srp, rc ); }
/** * Dump LACP packet * * @v iobuf I/O buffer * @v netdev Network device * @v label "RX" or "TX" */ static void eth_slow_lacp_dump ( struct io_buffer *iobuf, struct net_device *netdev, const char *label ) { union eth_slow_packet *eth_slow = iobuf->data; struct eth_slow_lacp *lacp = ð_slow->lacp; DBGC ( netdev, "SLOW %s %s LACP actor (%04x,%s,%04x,%02x,%04x) [%s]\n", netdev->name, label, ntohs ( lacp->actor.system_priority ), eth_ntoa ( lacp->actor.system ), ntohs ( lacp->actor.key ), ntohs ( lacp->actor.port_priority ), ntohs ( lacp->actor.port ), eth_slow_lacp_state_name ( lacp->actor.state ) ); DBGC ( netdev, "SLOW %s %s LACP partner (%04x,%s,%04x,%02x,%04x) [%s]\n", netdev->name, label, ntohs ( lacp->partner.system_priority ), eth_ntoa ( lacp->partner.system ), ntohs ( lacp->partner.key ), ntohs ( lacp->partner.port_priority ), ntohs ( lacp->partner.port ), eth_slow_lacp_state_name ( lacp->partner.state ) ); DBGC ( netdev, "SLOW %s %s LACP collector %04x (%d us)\n", netdev->name, label, ntohs ( lacp->collector.max_delay ), ( ntohs ( lacp->collector.max_delay ) * 10 ) ); DBGC2_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) ); }
/** * Build OCSP request * * @v ocsp OCSP check * @ret rc Return status code */ static int ocsp_request ( struct ocsp_check *ocsp ) { struct digest_algorithm *digest = &ocsp_digest_algorithm; struct asn1_builder *builder = &ocsp->request.builder; struct asn1_cursor *cert_id_tail = &ocsp->request.cert_id_tail; uint8_t digest_ctx[digest->ctxsize]; uint8_t name_digest[digest->digestsize]; uint8_t pubkey_digest[digest->digestsize]; int rc; /* Generate digests */ digest_init ( digest, digest_ctx ); digest_update ( digest, digest_ctx, ocsp->cert->issuer.raw.data, ocsp->cert->issuer.raw.len ); digest_final ( digest, digest_ctx, name_digest ); digest_init ( digest, digest_ctx ); digest_update ( digest, digest_ctx, ocsp->issuer->subject.public_key.raw_bits.data, ocsp->issuer->subject.public_key.raw_bits.len ); digest_final ( digest, digest_ctx, pubkey_digest ); /* Construct request */ if ( ( rc = ( asn1_prepend_raw ( builder, ocsp->cert->serial.raw.data, ocsp->cert->serial.raw.len ), asn1_prepend ( builder, ASN1_OCTET_STRING, pubkey_digest, sizeof ( pubkey_digest ) ), asn1_prepend ( builder, ASN1_OCTET_STRING, name_digest, sizeof ( name_digest ) ), asn1_prepend ( builder, ASN1_SEQUENCE, ocsp_algorithm_id, sizeof ( ocsp_algorithm_id ) ), asn1_wrap ( builder, ASN1_SEQUENCE ), asn1_wrap ( builder, ASN1_SEQUENCE ), asn1_wrap ( builder, ASN1_SEQUENCE ), asn1_wrap ( builder, ASN1_SEQUENCE ), asn1_wrap ( builder, ASN1_SEQUENCE ) ) ) != 0 ) { DBGC ( ocsp, "OCSP %p \"%s\" could not build request: %s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ) ); return rc; } DBGC2 ( ocsp, "OCSP %p \"%s\" request is:\n", ocsp, x509_name ( ocsp->cert ) ); DBGC2_HDA ( ocsp, 0, builder->data, builder->len ); /* Parse certificate ID for comparison with response */ cert_id_tail->data = builder->data; cert_id_tail->len = builder->len; if ( ( rc = ( asn1_enter ( cert_id_tail, ASN1_SEQUENCE ), asn1_enter ( cert_id_tail, ASN1_SEQUENCE ), asn1_enter ( cert_id_tail, ASN1_SEQUENCE ), asn1_enter ( cert_id_tail, ASN1_SEQUENCE ), asn1_enter ( cert_id_tail, ASN1_SEQUENCE ), asn1_skip ( cert_id_tail, ASN1_SEQUENCE ) ) ) != 0 ) { DBGC ( ocsp, "OCSP %p \"%s\" could not locate certID: %s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ) ); return rc; } return 0; }
/** * Dump marker packet * * @v iobuf I/O buffer * @v netdev Network device * @v label "RX" or "TX" */ static void eth_slow_marker_dump ( struct io_buffer *iobuf, struct net_device *netdev, const char *label ) { union eth_slow_packet *eth_slow = iobuf->data; struct eth_slow_marker *marker = ð_slow->marker; DBGC ( netdev, "SLOW %s %s marker %s port %04x system %s xact %08x\n", netdev->name, label, eth_slow_marker_tlv_name ( marker->marker.tlv.type ), ntohs ( marker->marker.port ), eth_ntoa ( marker->marker.system ), ntohl ( marker->marker.xact ) ); DBGC2_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) ); }
/** * Initiate SRP login * * @v srp SRP device */ static void srp_login ( struct srp_device *srp ) { struct io_buffer *iobuf; struct srp_login_req *login_req; int rc; assert ( ! ( srp->state & SRP_STATE_SOCKET_OPEN ) ); /* Open underlying socket */ if ( ( rc = srp->transport->connect ( srp ) ) != 0 ) { DBGC ( srp, "SRP %p could not open socket: %s\n", srp, strerror ( rc ) ); goto err; } srp->state |= SRP_STATE_SOCKET_OPEN; /* Allocate I/O buffer */ iobuf = xfer_alloc_iob ( &srp->socket, sizeof ( *login_req ) ); if ( ! iobuf ) { rc = -ENOMEM; goto err; } /* Construct login request IU */ login_req = iob_put ( iobuf, sizeof ( *login_req ) ); memset ( login_req, 0, sizeof ( *login_req ) ); login_req->type = SRP_LOGIN_REQ; login_req->tag.dwords[1] = htonl ( ++srp_tag ); login_req->max_i_t_iu_len = htonl ( SRP_MAX_I_T_IU_LEN ); login_req->required_buffer_formats = SRP_LOGIN_REQ_FMT_DDBD; memcpy ( &login_req->port_ids, &srp->port_ids, sizeof ( login_req->port_ids ) ); DBGC2 ( srp, "SRP %p TX login request tag %08x%08x\n", srp, ntohl ( login_req->tag.dwords[0] ), ntohl ( login_req->tag.dwords[1] ) ); DBGC2_HDA ( srp, 0, iobuf->data, iob_len ( iobuf ) ); /* Send login request IU */ if ( ( rc = xfer_deliver_iob ( &srp->socket, iobuf ) ) != 0 ) { DBGC ( srp, "SRP %p could not send login request: %s\n", srp, strerror ( rc ) ); goto err; } return; err: srp_fail ( srp, rc ); }
/** * Manage receive filters * * @v snp SNP interface * @v enable Receive filters to enable * @v disable Receive filters to disable * @v mcast_reset Reset multicast filters * @v mcast_count Number of multicast filters * @v mcast Multicast filters * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable, UINT32 disable, BOOLEAN mcast_reset, UINTN mcast_count, EFI_MAC_ADDRESS *mcast ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); unsigned int i; DBGC2 ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n", snpdev, enable, disable, ( mcast_reset ? " reset" : "" ), ( ( unsigned long ) mcast_count ) ); for ( i = 0 ; i < mcast_count ; i++ ) { DBGC2_HDA ( snpdev, i, &mcast[i], snpdev->netdev->ll_protocol->ll_addr_len ); } /* Lie through our teeth, otherwise MNP refuses to accept us */ return 0; }
/** * Transmit Fibre Channel ELS frame * * @v els Fibre Channel ELS transaction * @v data Data to transmit * @v len Length of data * @ret rc Return status code */ int fc_els_tx ( struct fc_els *els, const void *data, size_t len ) { struct xfer_metadata meta; struct sockaddr_fc dest; int rc; DBGC2 ( els, FCELS_FMT " transmitting:\n", FCELS_ARGS ( els ) ); DBGC2_HDA ( els, 0, data, len ); /* Construct metadata */ memset ( &meta, 0, sizeof ( meta ) ); meta.flags = ( fc_els_is_request ( els ) ? XFER_FL_OVER : ( XFER_FL_RESPONSE | XFER_FL_OUT ) ); meta.dest = fc_fill_sockaddr ( &dest, &els->peer_port_id ); /* Transmit frame */ if ( ( rc = xfer_deliver_raw_meta ( &els->xchg, data, len, &meta ) ) != 0 ) { DBGC ( els, FCELS_FMT " could not deliver frame: %s\n", FCELS_ARGS ( els ), strerror ( rc ) ); return rc; } return 0; }
/** * Receive Fibre Channel ELS frame * * @v els Fibre Channel ELS transaction * @v iobuf I/O buffer * @v meta Data transfer metadata * @ret rc Return status code */ static int fc_els_rx ( struct fc_els *els, struct io_buffer *iobuf, struct xfer_metadata *meta ) { struct fc_els_frame_common *frame = iobuf->data; struct sockaddr_fc *src = ( ( struct sockaddr_fc * ) meta->src ); struct sockaddr_fc *dest = ( ( struct sockaddr_fc * ) meta->dest ); size_t len = iob_len ( iobuf ); int rc; /* Sanity check */ if ( len < sizeof ( *frame ) ) { DBGC ( els, FCELS_FMT " received underlength frame:\n", FCELS_ARGS ( els ) ); DBGC_HDA ( els, 0, frame, len ); rc = -EINVAL; goto done; } if ( ! src ) { DBGC ( els, FCELS_FMT " received frame missing source " "address:\n", FCELS_ARGS ( els ) ); rc = -EINVAL; goto done; } if ( ! dest ) { DBGC ( els, FCELS_FMT " received frame missing destination " "address:\n", FCELS_ARGS ( els ) ); rc = -EINVAL; goto done; } /* Check for rejection responses */ if ( fc_els_is_request ( els ) && ( frame->command != FC_ELS_LS_ACC ) ) { DBGC ( els, FCELS_FMT " rejected:\n", FCELS_ARGS ( els ) ); DBGC_HDA ( els, 0, frame, len ); rc = -EACCES; goto done; } /* Update port IDs */ memcpy ( &els->port_id, &dest->sfc_port_id, sizeof ( els->port_id ) ); memcpy ( &els->peer_port_id, &src->sfc_port_id, sizeof ( els->peer_port_id ) ); /* Determine handler, if necessary */ if ( ! els->handler ) els->handler = fc_els_detect ( els, frame, len ); if ( ! els->handler ) els->handler = &fc_els_unknown_handler; DBGC2 ( els, FCELS_FMT " received:\n", FCELS_ARGS ( els ) ); DBGC2_HDA ( els, 0, frame, len ); /* Handle received frame */ if ( ( rc = els->handler->rx ( els, frame, len ) ) != 0 ) { DBGC ( els, FCELS_FMT " could not handle received frame: " "%s\n", FCELS_ARGS ( els ), strerror ( rc ) ); DBGC_HDA ( els, 0, frame, len ); goto done; } done: /* Free I/O buffer */ free_iob ( iobuf ); /* Close transaction */ fc_els_close ( els, rc ); return rc; }