Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarrod Johnson committed Sep 20, 2011
2 parents 76dadb0 + 12767d2 commit bd51f6f
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 33 deletions.
9 changes: 6 additions & 3 deletions src/include/ipxe/dhcp.h
Expand Up @@ -660,15 +660,18 @@ struct dhcphdr {
/** Setting block name used for BootServerDHCP responses */
#define PXEBS_SETTINGS_NAME "pxebs"

extern uint32_t dhcp_last_xid;
extern unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr,
uint16_t *flags );
extern int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
struct net_device *netdev, uint8_t msgtype,
const void *options, size_t options_len,
void *data, size_t max_len );
uint32_t xid, const void *options,
size_t options_len, void *data,
size_t max_len );
extern int dhcp_create_request ( struct dhcp_packet *dhcppkt,
struct net_device *netdev,
unsigned int msgtype, struct in_addr ciaddr,
unsigned int msgtype, uint32_t xid,
struct in_addr ciaddr,
void *data, size_t max_len );
extern int start_dhcp ( struct interface *job, struct net_device *netdev );
extern int start_pxebs ( struct interface *job, struct net_device *netdev,
Expand Down
10 changes: 10 additions & 0 deletions src/include/ipxe/tcp.h
Expand Up @@ -308,6 +308,16 @@ struct tcp_options {
*/
#define TCP_MSL ( 2 * 60 * TICKS_PER_SEC )

/**
* TCP maximum header length
*
*/
#define TCP_MAX_HEADER_LEN \
( MAX_LL_NET_HEADER_LEN + \
sizeof ( struct tcp_header ) + \
sizeof ( struct tcp_mss_option ) + \
sizeof ( struct tcp_timestamp_padded_option ) )

/**
* Compare TCP sequence numbers
*
Expand Down
9 changes: 6 additions & 3 deletions src/net/fakedhcp.c
Expand Up @@ -114,7 +114,8 @@ int create_fakedhcpdiscover ( struct net_device *netdev,
int rc;

if ( ( rc = dhcp_create_request ( &dhcppkt, netdev, DHCPDISCOVER,
ciaddr, data, max_len ) ) != 0 ) {
dhcp_last_xid, ciaddr, data,
max_len ) ) != 0 ) {
DBG ( "Could not create DHCPDISCOVER: %s\n",
strerror ( rc ) );
return rc;
Expand All @@ -139,7 +140,8 @@ int create_fakedhcpack ( struct net_device *netdev,
int rc;

/* Create base DHCPACK packet */
if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0,
if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK,
dhcp_last_xid, NULL, 0,
data, max_len ) ) != 0 ) {
DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) );
return rc;
Expand Down Expand Up @@ -190,7 +192,8 @@ int create_fakepxebsack ( struct net_device *netdev,
}

/* Create base DHCPACK packet */
if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0,
if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK,
dhcp_last_xid, NULL, 0,
data, max_len ) ) != 0 ) {
DBG ( "Could not create PXE BS ACK: %s\n",
strerror ( rc ) );
Expand Down
8 changes: 4 additions & 4 deletions src/net/tcp.c
Expand Up @@ -509,14 +509,14 @@ static int tcp_xmit ( struct tcp_connection *tcp ) {
start_timer ( &tcp->timer );

/* Allocate I/O buffer */
iobuf = alloc_iob ( len + MAX_LL_NET_HEADER_LEN );
iobuf = alloc_iob ( len + TCP_MAX_HEADER_LEN );
if ( ! iobuf ) {
DBGC ( tcp, "TCP %p could not allocate iobuf for %08x..%08x "
"%08x\n", tcp, tcp->snd_seq, ( tcp->snd_seq + seq_len ),
tcp->rcv_ack );
return -ENOMEM;
}
iob_reserve ( iobuf, MAX_LL_NET_HEADER_LEN );
iob_reserve ( iobuf, TCP_MAX_HEADER_LEN );

/* Fill data payload from transmit queue */
tcp_process_tx_queue ( tcp, len, iobuf, 0 );
Expand Down Expand Up @@ -653,14 +653,14 @@ static int tcp_xmit_reset ( struct tcp_connection *tcp,
int rc;

/* Allocate space for dataless TX buffer */
iobuf = alloc_iob ( MAX_LL_NET_HEADER_LEN );
iobuf = alloc_iob ( TCP_MAX_HEADER_LEN );
if ( ! iobuf ) {
DBGC ( tcp, "TCP %p could not allocate iobuf for RST "
"%08x..%08x %08x\n", tcp, ntohl ( in_tcphdr->ack ),
ntohl ( in_tcphdr->ack ), ntohl ( in_tcphdr->seq ) );
return -ENOMEM;
}
iob_reserve ( iobuf, MAX_LL_NET_HEADER_LEN );
iob_reserve ( iobuf, TCP_MAX_HEADER_LEN );

/* Construct RST response */
tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) );
Expand Down
47 changes: 24 additions & 23 deletions src/net/udp/dhcp.c
Expand Up @@ -116,6 +116,14 @@ struct setting use_cached_setting __setting ( SETTING_MISC ) = {
.type = &setting_type_uint8,
};

/**
* Most recent DHCP transaction ID
*
* This is exposed for use by the fakedhcp code when reconstructing
* DHCP packets for PXE NBPs.
*/
uint32_t dhcp_last_xid;

/**
* Name a DHCP packet type
*
Expand All @@ -137,23 +145,6 @@ static inline const char * dhcp_msgtype_name ( unsigned int msgtype ) {
}
}

/**
* Calculate DHCP transaction ID for a network device
*
* @v netdev Network device
* @ret xid DHCP XID
*
* Extract the least significant bits of the hardware address for use
* as the transaction ID.
*/
static uint32_t dhcp_xid ( struct net_device *netdev ) {
uint32_t xid;

memcpy ( &xid, ( netdev->ll_addr + netdev->ll_protocol->ll_addr_len
- sizeof ( xid ) ), sizeof ( xid ) );
return xid;
}

/****************************************************************************
*
* DHCP session
Expand Down Expand Up @@ -219,6 +210,8 @@ struct dhcp_session {
struct sockaddr_in local;
/** State of the session */
struct dhcp_session_state *state;
/** Transaction ID (in network-endian order) */
uint32_t xid;

/** Offered IP address */
struct in_addr offer;
Expand Down Expand Up @@ -916,6 +909,7 @@ unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr,
* @v dhcppkt DHCP packet structure to fill in
* @v netdev Network device
* @v msgtype DHCP message type
* @v xid Transaction ID (in network-endian order)
* @v options Initial options to include (or NULL)
* @v options_len Length of initial options
* @v data Buffer for DHCP packet
Expand All @@ -927,7 +921,7 @@ unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr,
*/
int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
struct net_device *netdev, uint8_t msgtype,
const void *options, size_t options_len,
uint32_t xid, const void *options, size_t options_len,
void *data, size_t max_len ) {
struct dhcphdr *dhcphdr = data;
int rc;
Expand All @@ -938,7 +932,7 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt,

/* Initialise DHCP packet content */
memset ( dhcphdr, 0, max_len );
dhcphdr->xid = dhcp_xid ( netdev );
dhcphdr->xid = xid;
dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
dhcphdr->op = dhcp_op[msgtype];
Expand All @@ -964,6 +958,7 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
* @v dhcppkt DHCP packet structure to fill in
* @v netdev Network device
* @v msgtype DHCP message type
* @v xid Transaction ID (in network-endian order)
* @v ciaddr Client IP address
* @v data Buffer for DHCP packet
* @v max_len Size of DHCP packet buffer
Expand All @@ -974,7 +969,8 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
*/
int dhcp_create_request ( struct dhcp_packet *dhcppkt,
struct net_device *netdev, unsigned int msgtype,
struct in_addr ciaddr, void *data, size_t max_len ) {
uint32_t xid, struct in_addr ciaddr,
void *data, size_t max_len ) {
struct dhcp_netdev_desc dhcp_desc;
struct dhcp_client_id client_id;
struct dhcp_client_uuid client_uuid;
Expand All @@ -985,7 +981,7 @@ int dhcp_create_request ( struct dhcp_packet *dhcppkt,
int rc;

/* Create DHCP packet */
if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype,
if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype, xid,
dhcp_request_options_data,
sizeof ( dhcp_request_options_data ),
data, max_len ) ) != 0 ) {
Expand Down Expand Up @@ -1099,7 +1095,8 @@ static int dhcp_tx ( struct dhcp_session *dhcp ) {

/* Create basic DHCP packet in temporary buffer */
if ( ( rc = dhcp_create_request ( &dhcppkt, dhcp->netdev, msgtype,
dhcp->local.sin_addr, iobuf->data,
dhcp->xid, dhcp->local.sin_addr,
iobuf->data,
iob_tailroom ( iobuf ) ) ) != 0 ) {
DBGC ( dhcp, "DHCP %p could not construct DHCP request: %s\n",
dhcp, strerror ( rc ) );
Expand Down Expand Up @@ -1187,7 +1184,7 @@ static int dhcp_deliver ( struct dhcp_session *dhcp,
&server_id, sizeof ( server_id ) );

/* Check for matching transaction ID */
if ( dhcphdr->xid != dhcp_xid ( dhcp->netdev ) ) {
if ( dhcphdr->xid != dhcp->xid ) {
DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
"ID\n", dhcp, dhcp_msgtype_name ( msgtype ),
inet_ntoa ( peer->sin_addr ),
Expand Down Expand Up @@ -1311,6 +1308,10 @@ int start_dhcp ( struct interface *job, struct net_device *netdev ) {
dhcp->netdev = netdev_get ( netdev );
dhcp->local.sin_family = AF_INET;
dhcp->local.sin_port = htons ( BOOTPC_PORT );
dhcp->xid = random();

/* Store DHCP transaction ID for fakedhcp code */
dhcp_last_xid = dhcp->xid;

/* Instantiate child objects and attach to our interfaces */
if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,
Expand Down
54 changes: 54 additions & 0 deletions src/util/romcheck.pl
@@ -0,0 +1,54 @@
#!/usr/bin/perl -w

use strict;
use warnings;

use constant DEVICES => "/proc/bus/pci/devices";

open my $fh, DEVICES
or die "Could not open ".DEVICES.": $!";

while ( ( my $line = <$fh> ) ) {

# Parse line from /proc/bus/pci/devices
chomp $line;
( my $bus, my $devfn, my $vendor, my $device, my $irq, my $bars, my $lengths,
my $driver )
= ( $line =~ /^ ([0-9a-f]{2}) ([0-9a-f]{2}) \s+
([0-9a-f]{4}) ([0-9a-f]{4}) \s+ ([0-9a-f]+) \s+
((?:[0-9a-f]+\s+){7}) ((?:[0-9a-f]+\s+){7})
(.+)?$/x )
or die "Invalid line \"".$line."\"\n";
( $bus, $devfn, $vendor, $device, $irq ) =
map { hex ( $_ ) } ( $bus, $devfn, $vendor, $device, $irq );
my $dev = ( $devfn >> 3 );
my $fn = ( $devfn & 0x7 );
$bars = [ map { hex ( $_ ) } split ( /\s+/, $bars ) ];
$lengths = [ map { hex ( $_ ) } split ( /\s+/, $lengths ) ];

# Calculate expansion ROM BAR presence and length
my $rom_length = $lengths->[6];

# Look for a BAR that could support a .mrom
my $mrom_ok;
if ( $rom_length ) {
for ( my $bar = 0 ; $bar < 7 ; $bar++ ) {
# Skip I/O BARs
next if $bars->[$bar] & 0x01;
# Skip low half of 64-bit BARs
$bar++ if $bars->[$bar] & 0x04;
# Skip 64-bit BARs with high dword set
next if $bars->[$bar] >> 32;
# Skip BARs smaller than the expansion ROM BAR
next if $lengths->[$bar] < $rom_length;
# This BAR is usable!
$mrom_ok = 1;
last;
}
}

printf "%02x:%02x.%x (%04x:%04x)", $bus, $dev, $fn, $vendor, $device;
printf " supports a %dkB .rom", ( $rom_length / 1024 ) if $rom_length;
printf " or .mrom" if $mrom_ok;
printf "\n";
}

0 comments on commit bd51f6f

Please sign in to comment.