iPXE
cachedhcp.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <ipxe/dhcppkt.h>
29 #include <ipxe/init.h>
30 #include <ipxe/netdevice.h>
31 #include <realmode.h>
32 #include <pxe_api.h>
33 
34 /** @file
35  *
36  * Cached DHCP packet
37  *
38  */
39 
40 /** Cached DHCPACK physical address
41  *
42  * This can be set by the prefix.
43  */
45 #define cached_dhcpack_phys __use_data16 ( cached_dhcpack_phys )
46 
47 /** Colour for debug messages */
48 #define colour &cached_dhcpack_phys
49 
50 /** Cached DHCPACK */
51 static struct dhcp_packet *cached_dhcpack;
52 
53 /**
54  * Cached DHCPACK startup function
55  *
56  */
57 static void cachedhcp_init ( void ) {
58  struct dhcp_packet *dhcppkt;
59  struct dhcp_packet *tmp;
60  struct dhcphdr *dhcphdr;
61  size_t max_len;
62  size_t len;
63 
64  /* Do nothing if no cached DHCPACK is present */
65  if ( ! cached_dhcpack_phys ) {
66  DBGC ( colour, "CACHEDHCP found no cached DHCPACK\n" );
67  return;
68  }
69 
70  /* No reliable way to determine length before parsing packet;
71  * start by assuming maximum length permitted by PXE.
72  */
73  max_len = sizeof ( BOOTPLAYER_t );
74 
75  /* Allocate and populate DHCP packet */
76  dhcppkt = zalloc ( sizeof ( *dhcppkt ) + max_len );
77  if ( ! dhcppkt ) {
78  DBGC ( colour, "CACHEDHCP could not allocate copy\n" );
79  return;
80  }
81  dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( *dhcppkt ) );
83  max_len );
84  dhcppkt_init ( dhcppkt, dhcphdr, max_len );
85 
86  /* Shrink packet to required length. If reallocation fails,
87  * just continue to use the original packet and waste the
88  * unused space.
89  */
90  len = dhcppkt_len ( dhcppkt );
91  assert ( len <= max_len );
92  tmp = realloc ( dhcppkt, ( sizeof ( *dhcppkt ) + len ) );
93  if ( tmp )
94  dhcppkt = tmp;
95 
96  /* Reinitialise packet at new address */
97  dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( *dhcppkt ) );
98  dhcppkt_init ( dhcppkt, dhcphdr, len );
99 
100  /* Store as cached DHCPACK, and mark original copy as consumed */
101  DBGC ( colour, "CACHEDHCP found cached DHCPACK at %08x+%zx\n",
103  cached_dhcpack = dhcppkt;
105 }
106 
107 /**
108  * Cached DHCPACK startup function
109  *
110  */
111 static void cachedhcp_startup ( void ) {
112 
113  /* If cached DHCP packet was not claimed by any network device
114  * during startup, then free it.
115  */
116  if ( cached_dhcpack ) {
117  DBGC ( colour, "CACHEDHCP freeing unclaimed cached DHCPACK\n" );
120  }
121 }
122 
123 /** Cached DHCPACK initialisation function */
124 struct init_fn cachedhcp_init_fn __init_fn ( INIT_NORMAL ) = {
126 };
127 
128 /** Cached DHCPACK startup function */
129 struct startup_fn cachedhcp_startup_fn __startup_fn ( STARTUP_LATE ) = {
130  .name = "cachedhcp",
131  .startup = cachedhcp_startup,
132 };
133 
134 /**
135  * Apply cached DHCPACK to network device, if applicable
136  *
137  * @v netdev Network device
138  * @ret rc Return status code
139  */
140 static int cachedhcp_probe ( struct net_device *netdev ) {
142  int rc;
143 
144  /* Do nothing unless we have a cached DHCPACK */
145  if ( ! cached_dhcpack )
146  return 0;
147 
148  /* Do nothing unless cached DHCPACK's MAC address matches this
149  * network device.
150  */
152  ll_protocol->ll_addr_len ) != 0 ) {
153  DBGC ( colour, "CACHEDHCP cached DHCPACK does not match %s\n",
154  netdev->name );
155  return 0;
156  }
157  DBGC ( colour, "CACHEDHCP cached DHCPACK is for %s\n", netdev->name );
158 
159  /* Register as DHCP settings for this network device */
162  DHCP_SETTINGS_NAME ) ) != 0 ) {
163  DBGC ( colour, "CACHEDHCP could not register settings: %s\n",
164  strerror ( rc ) );
165  return rc;
166  }
167 
168  /* Claim cached DHCPACK */
171 
172  return 0;
173 }
174 
175 /** Cached DHCP packet network device driver */
176 struct net_driver cachedhcp_driver __net_driver = {
177  .name = "cachedhcp",
178  .probe = cachedhcp_probe,
179 };
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define colour
Colour for debug messages.
Definition: cachedhcp.c:48
A DHCP packet.
Definition: dhcppkt.h:20
static struct dhcp_packet * cached_dhcpack
Cached DHCPACK.
Definition: cachedhcp.c:51
uint8_t ll_addr_len
Link-layer address length.
Definition: netdevice.h:198
void(* initialise)(void)
Definition: init.h:15
static void size_t size_t max_len
Definition: entropy.h:153
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
#define DBGC(...)
Definition: compiler.h:505
static void cachedhcp_init(void)
Cached DHCPACK startup function.
Definition: cachedhcp.c:57
userptr_t phys_to_user(unsigned long phys_addr)
Convert physical address to user pointer.
static void cachedhcp_startup(void)
Cached DHCPACK startup function.
Definition: cachedhcp.c:111
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
struct net_driver cachedhcp_driver __net_driver
Cached DHCP packet network device driver.
Definition: cachedhcp.c:176
const char * name
Definition: init.h:42
A network upper-layer driver.
Definition: netdevice.h:461
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition: netdevice.h:577
A link-layer protocol.
Definition: netdevice.h:114
uint32_t __bss16(cached_dhcpack_phys)
Cached DHCPACK physical address.
#define STARTUP_LATE
Late startup.
Definition: init.h:64
A startup/shutdown function.
Definition: init.h:41
#define INIT_NORMAL
Normal initialisation.
Definition: init.h:30
const char * name
Name.
Definition: netdevice.h:463
An initialisation function.
Definition: init.h:14
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define DHCP_SETTINGS_NAME
Settings block name used for DHCP responses.
Definition: dhcp.h:686
static struct net_device * netdev
Definition: gdbudp.c:52
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
uint8_t chaddr[16]
Client hardware address.
Definition: dhcp.h:637
uint8_t * tmp
Definition: entropy.h:156
A network device.
Definition: netdevice.h:348
struct startup_fn cachedhcp_startup_fn __startup_fn(STARTUP_LATE)
Cached DHCPACK startup function.
Preboot eXecution Environment (PXE) API.
unsigned int uint32_t
Definition: stdint.h:12
struct settings settings
Settings interface.
Definition: dhcppkt.h:28
struct init_fn cachedhcp_init_fn __init_fn(INIT_NORMAL)
Cached DHCPACK initialisation function.
A DHCP header.
Definition: dhcp.h:591
Network device management.
static int cachedhcp_probe(struct net_device *netdev)
Apply cached DHCPACK to network device, if applicable.
Definition: cachedhcp.c:140
void dhcppkt_init(struct dhcp_packet *dhcppkt, struct dhcphdr *data, size_t len)
Initialise DHCP packet.
Definition: dhcppkt.c:300
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:358
struct dhcphdr * dhcphdr
The DHCP packet contents.
Definition: dhcppkt.h:24
struct bootph BOOTPLAYER_t
Definition: pxe_api.h:406
uint32_t len
Length.
Definition: ena.h:14
static void dhcppkt_put(struct dhcp_packet *dhcppkt)
Decrement reference count on DHCP packet.
Definition: dhcppkt.h:49
#define cached_dhcpack_phys
Definition: cachedhcp.c:45
DHCP packets.
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition: malloc.c:521
int register_settings(struct settings *settings, struct settings *parent, const char *name)
Register settings block.
Definition: settings.c:478
static int dhcppkt_len(struct dhcp_packet *dhcppkt)
Get used length of DHCP packet.
Definition: dhcppkt.h:59
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:381
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:98
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
struct ll_protocol * ll_protocol
Link-layer protocol.
Definition: netdevice.h:366