When performing a length check on untrusted received data, it is
preferable to assign the corresponding typed pointer only after
validating that the length is sufficient to contain the dereferenced
pointer type. This allows the compiler to catch any unintended
dereferences before the length check has taken place, and so hardens
the code against future potential changes.
This pattern of assigning the pointer only after the corresponding
length check is already fairly widespread, but there are still large
swathes of older code that use the less safe idiom of assigning the
pointer first (generally as part of the variable declaration).
Move an assortment of pointer assignments after their corresponding
length checks, and fix the few harmless premature dereferences that
were discovered in the process (e.g. using a potentially non-existent
IPv4 source address as a debug colour stream identifier).
This is not intended to be a comprehensive update of all such pointer
assignments, merely an improvement of those sites where assignments
are easily identifiable and trivially hardened.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
23 files changed:
*/
static int srp_login_rsp ( struct srp_device *srpdev,
const void *data, size_t len ) {
*/
static int srp_login_rsp ( struct srp_device *srpdev,
const void *data, size_t len ) {
- const struct srp_login_rsp *login_rsp = data;
+ const struct srp_login_rsp *login_rsp;
/* Sanity check */
if ( len < sizeof ( *login_rsp ) ) {
/* Sanity check */
if ( len < sizeof ( *login_rsp ) ) {
srpdev, len );
return -EINVAL;
}
srpdev, len );
return -EINVAL;
}
DBGC ( srpdev, "SRP %p tag %08x LOGIN_RSP:\n",
srpdev, ntohl ( login_rsp->tag.dwords[1] ) );
DBGC_HDA ( srpdev, 0, data, len );
DBGC ( srpdev, "SRP %p tag %08x LOGIN_RSP:\n",
srpdev, ntohl ( login_rsp->tag.dwords[1] ) );
DBGC_HDA ( srpdev, 0, data, len );
*/
static int srp_login_rej ( struct srp_device *srpdev,
const void *data, size_t len ) {
*/
static int srp_login_rej ( struct srp_device *srpdev,
const void *data, size_t len ) {
- const struct srp_login_rej *login_rej = data;
+ const struct srp_login_rej *login_rej;
uint32_t reason;
/* Sanity check */
uint32_t reason;
/* Sanity check */
srpdev, len );
return -EINVAL;
}
srpdev, len );
return -EINVAL;
}
reason = ntohl ( login_rej->reason );
DBGC ( srpdev, "SRP %p tag %08x LOGIN_REJ reason %08x:\n",
srpdev, ntohl ( login_rej->tag.dwords[1] ), reason );
reason = ntohl ( login_rej->reason );
DBGC ( srpdev, "SRP %p tag %08x LOGIN_REJ reason %08x:\n",
srpdev, ntohl ( login_rej->tag.dwords[1] ), reason );
static int srpdev_deliver ( struct srp_device *srpdev,
struct io_buffer *iobuf,
struct xfer_metadata *meta __unused ) {
static int srpdev_deliver ( struct srp_device *srpdev,
struct io_buffer *iobuf,
struct xfer_metadata *meta __unused ) {
- struct srp_common *common = iobuf->data;
+ struct srp_common *common;
int ( * type ) ( struct srp_device *srp, const void *data, size_t len );
int rc;
int ( * type ) ( struct srp_device *srp, const void *data, size_t len );
int rc;
rc = -EINVAL;
goto err;
}
rc = -EINVAL;
goto err;
}
/* Determine IU type */
switch ( common->type ) {
/* Determine IU type */
switch ( common->type ) {
* @v iobuf I/O buffer
*/
static void imux_rx_tcp ( struct imux *imux, struct io_buffer *iobuf ) {
* @v iobuf I/O buffer
*/
static void imux_rx_tcp ( struct imux *imux, struct io_buffer *iobuf ) {
- struct imux_header_tcp *tcp = iobuf->data;
+ struct imux_header_tcp *tcp;
size_t len = iob_len ( iobuf );
int rc;
/* Sanity check */
if ( len < sizeof ( *tcp ) ) {
DBGC ( imux, "IMUX %p malformed TCP message:\n", imux );
size_t len = iob_len ( iobuf );
int rc;
/* Sanity check */
if ( len < sizeof ( *tcp ) ) {
DBGC ( imux, "IMUX %p malformed TCP message:\n", imux );
- DBGC_HDA ( imux, 0, tcp, len );
+ DBGC_HDA ( imux, 0, iobuf->data, len );
/* Ignore unexpected packets */
if ( tcp->tcp.dest != htons ( imux->port ) ) {
/* Ignore unexpected packets */
if ( tcp->tcp.dest != htons ( imux->port ) ) {
static void imux_in_complete ( struct usb_endpoint *ep,
struct io_buffer *iobuf, int rc ) {
struct imux *imux = container_of ( ep, struct imux, usbnet.in );
static void imux_in_complete ( struct usb_endpoint *ep,
struct io_buffer *iobuf, int rc ) {
struct imux *imux = container_of ( ep, struct imux, usbnet.in );
- struct imux_header *hdr = iobuf->data;
+ struct imux_header *hdr;
size_t len = iob_len ( iobuf );
/* Ignore packets cancelled when the endpoint closes */
size_t len = iob_len ( iobuf );
/* Ignore packets cancelled when the endpoint closes */
/* Sanity check */
if ( len < sizeof ( *hdr ) ) {
DBGC ( imux, "IMUX %p malformed message:\n", imux );
/* Sanity check */
if ( len < sizeof ( *hdr ) ) {
DBGC ( imux, "IMUX %p malformed message:\n", imux );
- DBGC_HDA ( imux, 0, hdr, len );
+ DBGC_HDA ( imux, 0, iobuf->data, len );
/* Record input sequence */
imux->in_seq = ntohs ( hdr->in_seq );
/* Record input sequence */
imux->in_seq = ntohs ( hdr->in_seq );
static int
netvsc_initialised ( struct netvsc_device *netvsc, const void *data,
size_t len ) {
static int
netvsc_initialised ( struct netvsc_device *netvsc, const void *data,
size_t len ) {
- const struct netvsc_init_completion *cmplt = data;
+ const struct netvsc_init_completion *cmplt;
/* Check completion */
if ( len < sizeof ( *cmplt ) ) {
/* Check completion */
if ( len < sizeof ( *cmplt ) ) {
"completion (%zd bytes)\n", netvsc->name, len );
return -EINVAL;
}
"completion (%zd bytes)\n", netvsc->name, len );
return -EINVAL;
}
if ( cmplt->header.type != cpu_to_le32 ( NETVSC_INIT_CMPLT ) ) {
DBGC ( netvsc, "NETVSC %s unexpected initialisation completion "
"type %d\n", netvsc->name,
if ( cmplt->header.type != cpu_to_le32 ( NETVSC_INIT_CMPLT ) ) {
DBGC ( netvsc, "NETVSC %s unexpected initialisation completion "
"type %d\n", netvsc->name,
*/
static int netvsc_rx_established_buffer ( struct netvsc_device *netvsc,
const void *data, size_t len ) {
*/
static int netvsc_rx_established_buffer ( struct netvsc_device *netvsc,
const void *data, size_t len ) {
- const struct netvsc_rx_establish_buffer_completion *cmplt = data;
+ const struct netvsc_rx_establish_buffer_completion *cmplt;
/* Check completion */
if ( len < sizeof ( *cmplt ) ) {
/* Check completion */
if ( len < sizeof ( *cmplt ) ) {
"bytes)\n", netvsc->name, len );
return -EINVAL;
}
"bytes)\n", netvsc->name, len );
return -EINVAL;
}
if ( cmplt->header.type != cpu_to_le32 ( NETVSC_RX_ESTABLISH_CMPLT ) ) {
DBGC ( netvsc, "NETVSC %s unexpected buffer completion type "
"%d\n", netvsc->name, le32_to_cpu ( cmplt->header.type));
if ( cmplt->header.type != cpu_to_le32 ( NETVSC_RX_ESTABLISH_CMPLT ) ) {
DBGC ( netvsc, "NETVSC %s unexpected buffer completion type "
"%d\n", netvsc->name, le32_to_cpu ( cmplt->header.type));
struct list_head *list ) {
struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
struct netvsc_device *netvsc = rndis->priv;
struct list_head *list ) {
struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
struct netvsc_device *netvsc = rndis->priv;
- const struct netvsc_rndis_message *msg = data;
+ const struct netvsc_rndis_message *msg;
struct io_buffer *iobuf;
struct io_buffer *tmp;
int rc;
struct io_buffer *iobuf;
struct io_buffer *tmp;
int rc;
rc = -EINVAL;
goto err_sanity;
}
rc = -EINVAL;
goto err_sanity;
}
if ( msg->header.type != cpu_to_le32 ( NETVSC_RNDIS_MSG ) ) {
DBGC ( netvsc, "NETVSC %s received unexpected RNDIS packet "
"type %d\n", netvsc->name,
if ( msg->header.type != cpu_to_le32 ( NETVSC_RNDIS_MSG ) ) {
DBGC ( netvsc, "NETVSC %s received unexpected RNDIS packet "
"type %d\n", netvsc->name,
static int aoecmd_rx ( struct aoe_command *aoecmd, struct io_buffer *iobuf,
const void *ll_source ) {
struct aoe_device *aoedev = aoecmd->aoedev;
static int aoecmd_rx ( struct aoe_command *aoecmd, struct io_buffer *iobuf,
const void *ll_source ) {
struct aoe_device *aoedev = aoecmd->aoedev;
- struct aoehdr *aoehdr = iobuf->data;
int rc;
/* Sanity check */
int rc;
/* Sanity check */
rc = -EINVAL;
goto done;
}
rc = -EINVAL;
goto done;
}
if ( ( ntohs ( aoehdr->major ) != aoedev->major ) ||
( aoehdr->minor != aoedev->minor ) ) {
DBGC ( aoedev, "AoE %s/%08x received response for incorrect "
if ( ( ntohs ( aoehdr->major ) != aoedev->major ) ||
( aoehdr->minor != aoedev->minor ) ) {
DBGC ( aoedev, "AoE %s/%08x received response for incorrect "
const void *ll_dest __unused,
const void *ll_source,
unsigned int flags __unused ) {
const void *ll_dest __unused,
const void *ll_source,
unsigned int flags __unused ) {
- struct aoehdr *aoehdr = iobuf->data;
struct aoe_command *aoecmd;
int rc;
struct aoe_command *aoecmd;
int rc;
rc = -EINVAL;
goto err_sanity;
}
rc = -EINVAL;
goto err_sanity;
}
if ( ( aoehdr->ver_flags & AOE_VERSION_MASK ) != AOE_VERSION ) {
DBG ( "AoE received packet for unsupported protocol version "
"%02x\n", ( aoehdr->ver_flags & AOE_VERSION_MASK ) );
if ( ( aoehdr->ver_flags & AOE_VERSION_MASK ) != AOE_VERSION ) {
DBG ( "AoE received packet for unsupported protocol version "
"%02x\n", ( aoehdr->ver_flags & AOE_VERSION_MASK ) );
const void *ll_dest __unused,
const void *ll_source __unused,
unsigned int flags __unused ) {
const void *ll_dest __unused,
const void *ll_source __unused,
unsigned int flags __unused ) {
- struct arphdr *arphdr = iobuf->data;
struct arp_net_protocol *arp_net_protocol;
struct net_protocol *net_protocol;
struct ll_protocol *ll_protocol;
struct arp_net_protocol *arp_net_protocol;
struct net_protocol *net_protocol;
struct ll_protocol *ll_protocol;
int rc;
/* Sanity check */
int rc;
/* Sanity check */
- if ( ( len < sizeof ( *arphdr ) ) || ( len < arp_len ( arphdr ) ) ) {
+ if ( len < sizeof ( *arphdr ) ) {
+ rc = -EINVAL;
+ goto done;
+ }
+ arphdr = iobuf->data;
+ if ( len < arp_len ( arphdr ) ) {
rc = -EINVAL;
goto done;
}
rc = -EINVAL;
goto done;
}
const void *ll_dest __unused,
const void *ll_source __unused,
unsigned int flags __unused ) {
const void *ll_dest __unused,
const void *ll_source __unused,
unsigned int flags __unused ) {
- union eth_slow_packet *eth_slow = iobuf->data;
+ union eth_slow_packet *eth_slow;
/* Sanity checks */
if ( iob_len ( iobuf ) < sizeof ( *eth_slow ) ) {
free_iob ( iobuf );
return -EINVAL;
}
/* Sanity checks */
if ( iob_len ( iobuf ) < sizeof ( *eth_slow ) ) {
free_iob ( iobuf );
return -EINVAL;
}
+ eth_slow = iobuf->data;
/* Strip any trailing padding */
iob_unput ( iobuf, ( iob_len ( iobuf ) - sizeof ( *eth_slow ) ) );
/* Strip any trailing padding */
iob_unput ( iobuf, ( iob_len ( iobuf ) - sizeof ( *eth_slow ) ) );
int eth_pull ( struct net_device *netdev __unused, struct io_buffer *iobuf,
const void **ll_dest, const void **ll_source,
uint16_t *net_proto, unsigned int *flags ) {
int eth_pull ( struct net_device *netdev __unused, struct io_buffer *iobuf,
const void **ll_dest, const void **ll_source,
uint16_t *net_proto, unsigned int *flags ) {
- struct ethhdr *ethhdr = iobuf->data;
uint16_t *llc_proto;
/* Sanity check. While in theory we could receive a one-byte
uint16_t *llc_proto;
/* Sanity check. While in theory we could receive a one-byte
iob_len ( iobuf ) );
return -EINVAL;
}
iob_len ( iobuf ) );
return -EINVAL;
}
/* Strip off Ethernet header */
iob_pull ( iobuf, sizeof ( *ethhdr ) );
/* Strip off Ethernet header */
iob_pull ( iobuf, sizeof ( *ethhdr ) );
*/
static int fc_port_deliver ( struct fc_port *port, struct io_buffer *iobuf,
struct xfer_metadata *meta ) {
*/
static int fc_port_deliver ( struct fc_port *port, struct io_buffer *iobuf,
struct xfer_metadata *meta ) {
- struct fc_frame_header *fchdr = iobuf->data;
+ struct fc_frame_header *fchdr;
unsigned int xchg_id;
struct fc_exchange *xchg;
int rc;
unsigned int xchg_id;
struct fc_exchange *xchg;
int rc;
rc = -EINVAL;
goto err_sanity;
}
rc = -EINVAL;
goto err_sanity;
}
/* Verify local port ID */
if ( ( memcmp ( &fchdr->d_id, &port->port_id,
/* Verify local port ID */
if ( ( memcmp ( &fchdr->d_id, &port->port_id,
static int fc_els_rx ( struct fc_els *els,
struct io_buffer *iobuf,
struct xfer_metadata *meta ) {
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 );
struct sockaddr_fc *src = ( ( struct sockaddr_fc * ) meta->src );
struct sockaddr_fc *dest = ( ( struct sockaddr_fc * ) meta->dest );
+ struct fc_els_frame_common *frame;
size_t len = iob_len ( iobuf );
int rc;
size_t len = iob_len ( iobuf );
int rc;
if ( len < sizeof ( *frame ) ) {
DBGC ( els, FCELS_FMT " received underlength frame:\n",
FCELS_ARGS ( els ) );
if ( len < sizeof ( *frame ) ) {
DBGC ( els, FCELS_FMT " received underlength frame:\n",
FCELS_ARGS ( els ) );
- DBGC_HDA ( els, 0, frame, len );
+ DBGC_HDA ( els, 0, iobuf->data, len );
rc = -EINVAL;
goto done;
}
rc = -EINVAL;
goto done;
}
if ( ! src ) {
DBGC ( els, FCELS_FMT " received frame missing source "
"address:\n", FCELS_ARGS ( els ) );
if ( ! src ) {
DBGC ( els, FCELS_FMT " received frame missing source "
"address:\n", FCELS_ARGS ( els ) );
* @ret rc Return status code
*/
static int fc_els_flogi_rx ( struct fc_els *els, void *data, size_t len ) {
* @ret rc Return status code
*/
static int fc_els_flogi_rx ( struct fc_els *els, void *data, size_t len ) {
- struct fc_login_frame *flogi = data;
+ struct fc_login_frame *flogi;
DBGC_HDA ( els, 0, data, len );
return -EINVAL;
}
DBGC_HDA ( els, 0, data, len );
return -EINVAL;
}
/* Extract parameters */
has_fabric = ( flogi->common.flags & htons ( FC_LOGIN_F_PORT ) );
/* Extract parameters */
has_fabric = ( flogi->common.flags & htons ( FC_LOGIN_F_PORT ) );
* @ret rc Return status code
*/
static int fc_els_plogi_rx ( struct fc_els *els, void *data, size_t len ) {
* @ret rc Return status code
*/
static int fc_els_plogi_rx ( struct fc_els *els, void *data, size_t len ) {
- struct fc_login_frame *plogi = data;
+ struct fc_login_frame *plogi;
struct fc_peer *peer;
int rc;
struct fc_peer *peer;
int rc;
rc = -EINVAL;
goto err_sanity;
}
rc = -EINVAL;
goto err_sanity;
}
if ( ! fc_link_ok ( &els->port->link ) ) {
DBGC ( els, FCELS_FMT " received while port link is down\n",
FCELS_ARGS ( els ) );
if ( ! fc_link_ok ( &els->port->link ) ) {
DBGC ( els, FCELS_FMT " received while port link is down\n",
FCELS_ARGS ( els ) );
*/
static int fc_els_logo_rx_request ( struct fc_els *els, void *data,
size_t len ) {
*/
static int fc_els_logo_rx_request ( struct fc_els *els, void *data,
size_t len ) {
- struct fc_logout_request_frame *logo = data;
+ struct fc_logout_request_frame *logo;
int rc;
/* Sanity check */
int rc;
/* Sanity check */
DBGC_HDA ( els, 0, data, len );
return -EINVAL;
}
DBGC_HDA ( els, 0, data, len );
return -EINVAL;
}
DBGC ( els, FCELS_FMT " has port %s as %s\n", FCELS_ARGS ( els ),
fc_ntoa ( &logo->port_wwn ), fc_id_ntoa ( &logo->port_id ) );
DBGC ( els, FCELS_FMT " has port %s as %s\n", FCELS_ARGS ( els ),
fc_ntoa ( &logo->port_wwn ), fc_id_ntoa ( &logo->port_id ) );
struct {
struct fc_prli_frame frame;
uint8_t param[descriptor->param_len];
struct {
struct fc_prli_frame frame;
uint8_t param[descriptor->param_len];
- } __attribute__ (( packed )) *prli = data;
+ } __attribute__ (( packed )) *prli;
struct fc_ulp *ulp;
int rc;
struct fc_ulp *ulp;
int rc;
rc = -EINVAL;
goto err_sanity;
}
rc = -EINVAL;
goto err_sanity;
}
DBGC ( els, FCELS_FMT " has parameters:\n", FCELS_ARGS ( els ) );
DBGC_HDA ( els, 0, prli->param, sizeof ( prli->param ) );
DBGC ( els, FCELS_FMT " has parameters:\n", FCELS_ARGS ( els ) );
DBGC_HDA ( els, 0, prli->param, sizeof ( prli->param ) );
const struct {
struct fc_prli_frame frame;
uint8_t param[descriptor->param_len];
const struct {
struct fc_prli_frame frame;
uint8_t param[descriptor->param_len];
- } __attribute__ (( packed )) *prli = data;
-
- /* Check for PRLI */
- if ( prli->frame.command != FC_ELS_PRLI )
- return -EINVAL;
+ } __attribute__ (( packed )) *prli;
/* Check for sufficient length to contain service parameter page */
if ( len < sizeof ( *prli ) )
return -EINVAL;
/* Check for sufficient length to contain service parameter page */
if ( len < sizeof ( *prli ) )
return -EINVAL;
+ prli = data;
+
+ /* Check for PRLI */
+ if ( prli->frame.command != FC_ELS_PRLI )
+ return -EINVAL;
/* Check for upper-layer protocol type */
if ( prli->frame.page.type != descriptor->type )
/* Check for upper-layer protocol type */
if ( prli->frame.page.type != descriptor->type )
*/
static int fc_els_echo_rx_response ( struct fc_els *els, void *data,
size_t len ) {
*/
static int fc_els_echo_rx_response ( struct fc_els *els, void *data,
size_t len ) {
- struct fc_echo_request_frame *echo = data;
+ struct fc_echo_request_frame *echo;
DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );
DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );
+ /* Sanity check */
+ if ( len != sizeof ( *echo ) ) {
+ DBGC ( els, FCELS_FMT " received underlength echo response\n",
+ FCELS_ARGS ( els ) );
+ DBGC_HDA ( els, 0, data, len );
+ return -EIO;
+ }
+ echo = data;
+
/* Check response is correct */
/* Check response is correct */
- if ( ( len != sizeof ( *echo ) ) ||
- ( echo->magic != htonl ( FC_ECHO_MAGIC ) ) ) {
+ if ( echo->magic != htonl ( FC_ECHO_MAGIC ) ) {
DBGC ( els, FCELS_FMT " received bad echo response\n",
FCELS_ARGS ( els ) );
DBGC_HDA ( els, 0, data, len );
DBGC ( els, FCELS_FMT " received bad echo response\n",
FCELS_ARGS ( els ) );
DBGC_HDA ( els, 0, data, len );
static int fc_ns_query_deliver ( struct fc_ns_query *query,
struct io_buffer *iobuf,
struct xfer_metadata *meta __unused ) {
static int fc_ns_query_deliver ( struct fc_ns_query *query,
struct io_buffer *iobuf,
struct xfer_metadata *meta __unused ) {
- union fc_ns_response *resp = iobuf->data;
+ union fc_ns_response *resp;
struct fc_port_id *peer_port_id;
int rc;
struct fc_port_id *peer_port_id;
int rc;
rc = -EINVAL;
goto done;
}
rc = -EINVAL;
goto done;
}
/* Handle response */
switch ( ntohs ( resp->ct.code ) ) {
/* Handle response */
switch ( ntohs ( resp->ct.code ) ) {
struct io_buffer *iobuf,
struct xfer_metadata *meta __unused ) {
struct fcp_device *fcpdev = fcpcmd->fcpdev;
struct io_buffer *iobuf,
struct xfer_metadata *meta __unused ) {
struct fcp_device *fcpdev = fcpcmd->fcpdev;
- struct fcp_xfer_rdy *xfer_rdy = iobuf->data;
+ struct fcp_xfer_rdy *xfer_rdy;
int rc;
/* Sanity checks */
int rc;
/* Sanity checks */
rc = -EPROTO;
goto done;
}
rc = -EPROTO;
goto done;
}
+ xfer_rdy = iobuf->data;
if ( ntohl ( xfer_rdy->offset ) != fcpcmd->offset ) {
/* We do not advertise out-of-order delivery */
DBGC ( fcpdev, "FCP %p xchg %04x cannot support out-of-order "
if ( ntohl ( xfer_rdy->offset ) != fcpcmd->offset ) {
/* We do not advertise out-of-order delivery */
DBGC ( fcpdev, "FCP %p xchg %04x cannot support out-of-order "
static int icmp_tx_echo_reply ( struct io_buffer *iobuf,
struct sockaddr_tcpip *st_dest,
struct icmp_echo_protocol *echo_protocol ) {
static int icmp_tx_echo_reply ( struct io_buffer *iobuf,
struct sockaddr_tcpip *st_dest,
struct icmp_echo_protocol *echo_protocol ) {
- struct icmp_echo *echo = iobuf->data;
+ struct icmp_echo *echo;
+ /* Sanity check: should have already been checked by receiver */
+ assert ( iob_len ( iobuf ) >= sizeof ( *echo ) );
+ echo = iobuf->data;
+
/* Set type */
echo->icmp.type = echo_protocol->reply;
/* Set type */
echo->icmp.type = echo_protocol->reply;
int icmp_rx_echo_request ( struct io_buffer *iobuf,
struct sockaddr_tcpip *st_src,
struct icmp_echo_protocol *echo_protocol ) {
int icmp_rx_echo_request ( struct io_buffer *iobuf,
struct sockaddr_tcpip *st_src,
struct icmp_echo_protocol *echo_protocol ) {
- struct icmp_echo *echo = iobuf->data;
+ struct icmp_echo *echo;
int rc;
/* Sanity check */
int rc;
/* Sanity check */
free_iob ( iobuf );
return -EINVAL;
}
free_iob ( iobuf );
return -EINVAL;
}
DBGC ( icmpcol ( st_src ), "ICMP RX echo request id %04x seq %04x\n",
ntohs ( echo->ident ), ntohs ( echo->sequence ) );
DBGC ( icmpcol ( st_src ), "ICMP RX echo request id %04x seq %04x\n",
ntohs ( echo->ident ), ntohs ( echo->sequence ) );
*/
int icmp_rx_echo_reply ( struct io_buffer *iobuf,
struct sockaddr_tcpip *st_src ) {
*/
int icmp_rx_echo_reply ( struct io_buffer *iobuf,
struct sockaddr_tcpip *st_src ) {
- struct icmp_echo *echo = iobuf->data;
+ struct icmp_echo *echo;
int rc;
/* Sanity check */
int rc;
/* Sanity check */
free_iob ( iobuf );
return -EINVAL;
}
free_iob ( iobuf );
return -EINVAL;
}
DBGC ( icmpcol ( st_src ), "ICMP RX echo reply id %04x seq %04x\n",
ntohs ( echo->ident ), ntohs ( echo->sequence ) );
DBGC ( icmpcol ( st_src ), "ICMP RX echo reply id %04x seq %04x\n",
ntohs ( echo->ident ), ntohs ( echo->sequence ) );
struct sockaddr_tcpip *st_src,
struct sockaddr_tcpip *st_dest __unused,
uint16_t pshdr_csum __unused ) {
struct sockaddr_tcpip *st_src,
struct sockaddr_tcpip *st_dest __unused,
uint16_t pshdr_csum __unused ) {
- struct icmp_header *icmp = iobuf->data;
+ struct icmp_header *icmp;
size_t len = iob_len ( iobuf );
unsigned int csum;
unsigned int type;
size_t len = iob_len ( iobuf );
unsigned int csum;
unsigned int type;
rc = -EINVAL;
goto discard;
}
rc = -EINVAL;
goto discard;
}
/* Verify checksum */
csum = tcpip_chksum ( icmp, len );
/* Verify checksum */
csum = tcpip_chksum ( icmp, len );
struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum ) {
struct sockaddr_in6 *sin6_src = ( ( struct sockaddr_in6 * ) st_src );
struct sockaddr_in6 *sin6_dest = ( ( struct sockaddr_in6 * ) st_dest );
struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum ) {
struct sockaddr_in6 *sin6_src = ( ( struct sockaddr_in6 * ) st_src );
struct sockaddr_in6 *sin6_dest = ( ( struct sockaddr_in6 * ) st_dest );
- struct icmp_header *icmp = iobuf->data;
+ struct icmp_header *icmp;
size_t len = iob_len ( iobuf );
struct icmpv6_handler *handler;
unsigned int csum;
size_t len = iob_len ( iobuf );
struct icmpv6_handler *handler;
unsigned int csum;
rc = -EINVAL;
goto done;
}
rc = -EINVAL;
goto done;
}
/* Verify checksum */
csum = tcpip_continue_chksum ( pshdr_csum, icmp, len );
/* Verify checksum */
csum = tcpip_continue_chksum ( pshdr_csum, icmp, len );
const void *ll_dest __unused,
const void *ll_source __unused,
unsigned int flags ) {
const void *ll_dest __unused,
const void *ll_source __unused,
unsigned int flags ) {
- struct iphdr *iphdr = iobuf->data;
size_t hdrlen;
size_t len;
union {
size_t hdrlen;
size_t len;
union {
/* Sanity check the IPv4 header */
if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
/* Sanity check the IPv4 header */
if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
- DBGC ( iphdr->src, "IPv4 packet too short at %zd bytes (min "
+ DBGC ( netdev, "IPv4 packet too short at %zd bytes (min "
"%zd bytes)\n", iob_len ( iobuf ), sizeof ( *iphdr ) );
goto err_header;
}
"%zd bytes)\n", iob_len ( iobuf ), sizeof ( *iphdr ) );
goto err_header;
}
if ( ( iphdr->verhdrlen & IP_MASK_VER ) != IP_VER ) {
DBGC ( iphdr->src, "IPv4 version %#02x not supported\n",
iphdr->verhdrlen );
if ( ( iphdr->verhdrlen & IP_MASK_VER ) != IP_VER ) {
DBGC ( iphdr->src, "IPv4 version %#02x not supported\n",
iphdr->verhdrlen );
const void *ll_dest __unused,
const void *ll_source __unused,
unsigned int flags __unused ) {
const void *ll_dest __unused,
const void *ll_source __unused,
unsigned int flags __unused ) {
- struct ipv6_header *iphdr = iobuf->data;
+ struct ipv6_header *iphdr;
union ipv6_extension_header *ext;
union {
struct sockaddr_in6 sin6;
union ipv6_extension_header *ext;
union {
struct sockaddr_in6 sin6;
/* Sanity check the IPv6 header */
if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
/* Sanity check the IPv6 header */
if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
- DBGC ( ipv6col ( &iphdr->src ), "IPv6 packet too short at %zd "
- "bytes (min %zd bytes)\n", iob_len ( iobuf ),
- sizeof ( *iphdr ) );
+ DBGC ( netdev, "IPv6 packet too short at %zd bytes (min %zd "
+ "bytes)\n", iob_len ( iobuf ), sizeof ( *iphdr ) );
rc = -EINVAL_LEN;
goto err_header;
}
rc = -EINVAL_LEN;
goto err_header;
}
if ( ( iphdr->ver_tc_label & htonl ( IPV6_MASK_VER ) ) !=
htonl ( IPV6_VER ) ) {
DBGC ( ipv6col ( &iphdr->src ), "IPv6 version %#08x not "
if ( ( iphdr->ver_tc_label & htonl ( IPV6_MASK_VER ) ) !=
htonl ( IPV6_VER ) ) {
DBGC ( ipv6col ( &iphdr->src ), "IPv6 version %#08x not "
* @ret rc Return status code
*/
int ping_rx ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src ) {
* @ret rc Return status code
*/
int ping_rx ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src ) {
- struct icmp_echo *echo = iobuf->data;
+ struct icmp_echo *echo;
struct ping_connection *ping;
struct xfer_metadata meta;
int rc;
/* Sanity check: should already have been checked by ICMP layer */
assert ( iob_len ( iobuf ) >= sizeof ( *echo ) );
struct ping_connection *ping;
struct xfer_metadata meta;
int rc;
/* Sanity check: should already have been checked by ICMP layer */
assert ( iob_len ( iobuf ) >= sizeof ( *echo ) );
/* Identify connection */
ping = ping_demux ( ntohs ( echo->ident ) );
/* Identify connection */
ping = ping_demux ( ntohs ( echo->ident ) );
struct sockaddr_tcpip *st_src,
struct sockaddr_tcpip *st_dest __unused,
uint16_t pshdr_csum ) {
struct sockaddr_tcpip *st_src,
struct sockaddr_tcpip *st_dest __unused,
uint16_t pshdr_csum ) {
- struct tcp_header *tcphdr = iobuf->data;
+ struct tcp_header *tcphdr;
struct tcp_connection *tcp;
struct tcp_options options;
size_t hlen;
struct tcp_connection *tcp;
struct tcp_options options;
size_t hlen;
rc = -EINVAL;
goto discard;
}
rc = -EINVAL;
goto discard;
}
hlen = ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ) * 4;
if ( hlen < sizeof ( *tcphdr ) ) {
DBG ( "TCP header too short at %zd bytes (min %zd bytes)\n",
hlen = ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ) * 4;
if ( hlen < sizeof ( *tcphdr ) ) {
DBG ( "TCP header too short at %zd bytes (min %zd bytes)\n",
struct net_device *netdev __unused,
struct sockaddr_tcpip *st_src,
struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum ) {
struct net_device *netdev __unused,
struct sockaddr_tcpip *st_src,
struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum ) {
- struct udp_header *udphdr = iobuf->data;
+ struct udp_header *udphdr;
struct udp_connection *udp;
struct xfer_metadata meta;
size_t ulen;
struct udp_connection *udp;
struct xfer_metadata meta;
size_t ulen;
if ( iob_len ( iobuf ) < sizeof ( *udphdr ) ) {
DBG ( "UDP packet too short at %zd bytes (min %zd bytes)\n",
iob_len ( iobuf ), sizeof ( *udphdr ) );
if ( iob_len ( iobuf ) < sizeof ( *udphdr ) ) {
DBG ( "UDP packet too short at %zd bytes (min %zd bytes)\n",
iob_len ( iobuf ), sizeof ( *udphdr ) );
rc = -EINVAL;
goto done;
}
rc = -EINVAL;
goto done;
}
ulen = ntohs ( udphdr->len );
if ( ulen < sizeof ( *udphdr ) ) {
DBG ( "UDP length too short at %zd bytes "
ulen = ntohs ( udphdr->len );
if ( ulen < sizeof ( *udphdr ) ) {
DBG ( "UDP length too short at %zd bytes "
struct xfer_metadata *meta ) {
struct settings *parent = netdev_settings ( dhcpv6->netdev );
struct sockaddr_in6 *src = ( ( struct sockaddr_in6 * ) meta->src );
struct xfer_metadata *meta ) {
struct settings *parent = netdev_settings ( dhcpv6->netdev );
struct sockaddr_in6 *src = ( ( struct sockaddr_in6 * ) meta->src );
- struct dhcpv6_header *dhcphdr = iobuf->data;
+ struct dhcpv6_header *dhcphdr;
struct dhcpv6_option_list options;
const union dhcpv6_any_option *option;
int rc;
struct dhcpv6_option_list options;
const union dhcpv6_any_option *option;
int rc;
rc = -EINVAL;
goto done;
}
rc = -EINVAL;
goto done;
}
assert ( src != NULL );
assert ( src->sin6_family == AF_INET6 );
DBGC ( dhcpv6, "DHCPv6 %s received %s from %s\n",
assert ( src != NULL );
assert ( src->sin6_family == AF_INET6 );
DBGC ( dhcpv6, "DHCPv6 %s received %s from %s\n",
static int dns_xfer_deliver ( struct dns_request *dns,
struct io_buffer *iobuf,
struct xfer_metadata *meta __unused ) {
static int dns_xfer_deliver ( struct dns_request *dns,
struct io_buffer *iobuf,
struct xfer_metadata *meta __unused ) {
- struct dns_header *response = iobuf->data;
struct dns_header *query = &dns->buf.query;
unsigned int qtype = dns->question->qtype;
struct dns_header *query = &dns->buf.query;
unsigned int qtype = dns->question->qtype;
+ struct dns_header *response;
struct dns_name buf;
union dns_rr *rr;
int offset;
struct dns_name buf;
union dns_rr *rr;
int offset;
rc = -EINVAL;
goto done;
}
rc = -EINVAL;
goto done;
}
+ response = iobuf->data;
/* Check response ID matches query ID */
if ( response->id != query->id ) {
/* Check response ID matches query ID */
if ( response->id != query->id ) {
* @ret rc Return status code
*/
static int tftp_rx_oack ( struct tftp_request *tftp, void *buf, size_t len ) {
* @ret rc Return status code
*/
static int tftp_rx_oack ( struct tftp_request *tftp, void *buf, size_t len ) {
- struct tftp_oack *oack = buf;
+ struct tftp_oack *oack;
char *end = buf + len;
char *name;
char *value;
char *end = buf + len;
char *name;
char *value;
rc = -EINVAL;
goto done;
}
rc = -EINVAL;
goto done;
}
/* Process each option in turn */
for ( name = oack->data ; name < end ; name = next ) {
/* Process each option in turn */
for ( name = oack->data ; name < end ; name = next ) {
*/
static int tftp_rx_data ( struct tftp_request *tftp,
struct io_buffer *iobuf ) {
*/
static int tftp_rx_data ( struct tftp_request *tftp,
struct io_buffer *iobuf ) {
- struct tftp_data *data = iobuf->data;
+ struct tftp_data *data;
struct xfer_metadata meta;
unsigned int block;
off_t offset;
struct xfer_metadata meta;
unsigned int block;
off_t offset;
rc = -EINVAL;
goto done;
}
rc = -EINVAL;
goto done;
}
/* Calculate block number */
block = ( ( bitmap_first_gap ( &tftp->bitmap ) + 1 ) & ~0xffff );
/* Calculate block number */
block = ( ( bitmap_first_gap ( &tftp->bitmap ) + 1 ) & ~0xffff );
* @ret rc Return status code
*/
static int tftp_rx_error ( struct tftp_request *tftp, void *buf, size_t len ) {
* @ret rc Return status code
*/
static int tftp_rx_error ( struct tftp_request *tftp, void *buf, size_t len ) {
- struct tftp_error *error = buf;
+ struct tftp_error *error;
int rc;
/* Sanity check */
int rc;
/* Sanity check */
"length %zd\n", tftp, len );
return -EINVAL;
}
"length %zd\n", tftp, len );
return -EINVAL;
}
DBGC ( tftp, "TFTP %p received ERROR packet with code %d, message "
"\"%s\"\n", tftp, ntohs ( error->errcode ), error->errmsg );
DBGC ( tftp, "TFTP %p received ERROR packet with code %d, message "
"\"%s\"\n", tftp, ntohs ( error->errcode ), error->errmsg );
struct io_buffer *iobuf,
struct xfer_metadata *meta ) {
struct sockaddr_tcpip *st_src;
struct io_buffer *iobuf,
struct xfer_metadata *meta ) {
struct sockaddr_tcpip *st_src;
- struct tftp_common *common = iobuf->data;
+ struct tftp_common *common;
size_t len = iob_len ( iobuf );
int rc = -EINVAL;
size_t len = iob_len ( iobuf );
int rc = -EINVAL;
"%zd\n", tftp, len );
goto done;
}
"%zd\n", tftp, len );
goto done;
}
if ( ! meta->src ) {
DBGC ( tftp, "TFTP %p received packet without source port\n",
tftp );
if ( ! meta->src ) {
DBGC ( tftp, "TFTP %p received packet without source port\n",
tftp );
static int vlan_rx ( struct io_buffer *iobuf, struct net_device *trunk,
const void *ll_dest, const void *ll_source,
unsigned int flags __unused ) {
static int vlan_rx ( struct io_buffer *iobuf, struct net_device *trunk,
const void *ll_dest, const void *ll_source,
unsigned int flags __unused ) {
- struct vlan_header *vlanhdr = iobuf->data;
+ struct vlan_header *vlanhdr;
struct net_device *netdev;
struct ll_protocol *ll_protocol;
uint8_t ll_dest_copy[ETH_ALEN];
struct net_device *netdev;
struct ll_protocol *ll_protocol;
uint8_t ll_dest_copy[ETH_ALEN];
rc = -EINVAL;
goto err_sanity;
}
rc = -EINVAL;
goto err_sanity;
}
/* Identify VLAN device */
tag = VLAN_TAG ( ntohs ( vlanhdr->tci ) );
/* Identify VLAN device */
tag = VLAN_TAG ( ntohs ( vlanhdr->tci ) );