iPXE
fakedhcp.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008 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 FILE_SECBOOT ( PERMITTED );
26 
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <ipxe/settings.h>
33 #include <ipxe/netdevice.h>
34 #include <ipxe/dhcppkt.h>
35 #include <ipxe/fakedhcp.h>
36 
37 /** @file
38  *
39  * Fake DHCP packets
40  *
41  */
42 
43 /**
44  * Copy settings to DHCP packet
45  *
46  * @v dest Destination DHCP packet
47  * @v source Source settings block
48  * @v encapsulator Encapsulating setting tag number, or zero
49  * @ret rc Return status code
50  */
51 static int copy_encap_settings ( struct dhcp_packet *dest,
52  struct settings *source,
53  unsigned int encapsulator ) {
54  struct setting setting = { .name = "" };
55  unsigned int subtag;
56  unsigned int tag;
57  void *data;
58  int len;
59  int rc;
60 
61  for ( subtag = DHCP_MIN_OPTION; subtag <= DHCP_MAX_OPTION; subtag++ ) {
62  tag = DHCP_ENCAP_OPT ( encapsulator, subtag );
63  switch ( tag ) {
64  case DHCP_EB_ENCAP:
65  case DHCP_VENDOR_ENCAP:
66  /* Process encapsulated settings */
67  if ( ( rc = copy_encap_settings ( dest, source,
68  tag ) ) != 0 )
69  return rc;
70  break;
71  default:
72  /* Copy setting, if present */
73  setting.tag = tag;
74  len = fetch_raw_setting_copy ( source, &setting, &data);
75  if ( len >= 0 ) {
76  rc = dhcppkt_store ( dest, tag, data, len );
77  free ( data );
78  if ( rc != 0 )
79  return rc;
80  }
81  break;
82  }
83  }
84 
85  return 0;
86 }
87 
88 /**
89  * Copy settings to DHCP packet
90  *
91  * @v dest Destination DHCP packet
92  * @v source Source settings block
93  * @ret rc Return status code
94  */
95 static int copy_settings ( struct dhcp_packet *dest,
96  struct settings *source ) {
97  return copy_encap_settings ( dest, source, 0 );
98 }
99 
100 /**
101  * Create fake DHCPDISCOVER packet
102  *
103  * @v netdev Network device
104  * @v data Buffer for DHCP packet
105  * @v max_len Size of DHCP packet buffer
106  * @ret rc Return status code
107  *
108  * Used by external code.
109  */
111  void *data, size_t max_len ) {
112  struct dhcp_packet dhcppkt;
113  struct in_addr ciaddr = { 0 };
114  int rc;
115 
116  if ( ( rc = dhcp_create_request ( &dhcppkt, netdev, DHCPDISCOVER,
117  dhcp_last_xid, ciaddr, data,
118  max_len ) ) != 0 ) {
119  DBG ( "Could not create DHCPDISCOVER: %s\n",
120  strerror ( rc ) );
121  return rc;
122  }
123 
124  return 0;
125 }
126 
127 /**
128  * Create fake DHCPACK packet
129  *
130  * @v netdev Network device
131  * @v data Buffer for DHCP packet
132  * @v max_len Size of DHCP packet buffer
133  * @ret rc Return status code
134  *
135  * Used by external code.
136  */
138  void *data, size_t max_len ) {
139  struct dhcp_packet dhcppkt;
140  int rc;
141 
142  /* Create base DHCPACK packet */
143  if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK,
144  dhcp_last_xid, NULL, 0,
145  data, max_len ) ) != 0 ) {
146  DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) );
147  return rc;
148  }
149 
150  /* Merge in globally-scoped settings, then netdev-specific
151  * settings. Do it in this order so that netdev-specific
152  * settings take precedence regardless of stated priorities.
153  */
154  if ( ( rc = copy_settings ( &dhcppkt, NULL ) ) != 0 ) {
155  DBG ( "Could not set DHCPACK global settings: %s\n",
156  strerror ( rc ) );
157  return rc;
158  }
159  if ( ( rc = copy_settings ( &dhcppkt,
160  netdev_settings ( netdev ) ) ) != 0 ) {
161  DBG ( "Could not set DHCPACK netdev settings: %s\n",
162  strerror ( rc ) );
163  return rc;
164  }
165 
166  return 0;
167 }
168 
169 /**
170  * Create fake PXE Boot Server ACK packet
171  *
172  * @v netdev Network device
173  * @v data Buffer for DHCP packet
174  * @v max_len Size of DHCP packet buffer
175  * @ret rc Return status code
176  *
177  * Used by external code.
178  */
180  void *data, size_t max_len ) {
181  struct dhcp_packet dhcppkt;
182  struct settings *proxy_settings;
183  struct settings *pxebs_settings;
184  int rc;
185 
186  /* Identify available settings */
187  proxy_settings = find_settings ( PROXYDHCP_SETTINGS_NAME );
188  pxebs_settings = find_settings ( PXEBS_SETTINGS_NAME );
189  if ( ( ! proxy_settings ) && ( ! pxebs_settings ) ) {
190  /* No PXE boot server; return the regular DHCPACK */
191  return create_fakedhcpack ( netdev, data, max_len );
192  }
193 
194  /* Create base DHCPACK packet */
195  if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK,
196  dhcp_last_xid, NULL, 0,
197  data, max_len ) ) != 0 ) {
198  DBG ( "Could not create PXE BS ACK: %s\n",
199  strerror ( rc ) );
200  return rc;
201  }
202 
203  /* Populate ciaddr */
205  &dhcppkt.dhcphdr->ciaddr );
206 
207  /* Merge in ProxyDHCP options */
208  if ( proxy_settings &&
209  ( ( rc = copy_settings ( &dhcppkt, proxy_settings ) ) != 0 ) ) {
210  DBG ( "Could not copy ProxyDHCP settings: %s\n",
211  strerror ( rc ) );
212  return rc;
213  }
214 
215  /* Merge in BootServerDHCP options, if present */
216  if ( pxebs_settings &&
217  ( ( rc = copy_settings ( &dhcppkt, pxebs_settings ) ) != 0 ) ) {
218  DBG ( "Could not copy PXE BS settings: %s\n",
219  strerror ( rc ) );
220  return rc;
221  }
222 
223  return 0;
224 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
A DHCP packet.
Definition: dhcppkt.h:21
#define DHCP_EB_ENCAP
Etherboot-specific encapsulated options.
Definition: dhcp.h:357
int fetch_raw_setting_copy(struct settings *settings, const struct setting *setting, void **data)
Fetch value of setting.
Definition: settings.c:822
Error codes.
int fetch_ipv4_setting(struct settings *settings, const struct setting *setting, struct in_addr *inp)
Fetch value of IPv4 address setting.
Definition: settings.c:913
int create_fakedhcpack(struct net_device *netdev, void *data, size_t max_len)
Create fake DHCPACK packet.
Definition: fakedhcp.c:137
const struct setting ip_setting
int dhcp_create_request(struct dhcp_packet *dhcppkt, struct net_device *netdev, unsigned int msgtype, uint32_t xid, struct in_addr ciaddr, void *data, size_t max_len)
Create DHCP request packet.
Definition: dhcp.c:1008
static int copy_settings(struct dhcp_packet *dest, struct settings *source)
Copy settings to DHCP packet.
Definition: fakedhcp.c:95
#define DHCP_MAX_OPTION
Maximum normal DHCP option.
Definition: dhcp.h:542
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition: netdevice.h:587
int create_fakedhcpdiscover(struct net_device *netdev, void *data, size_t max_len)
Create fake DHCPDISCOVER packet.
Definition: fakedhcp.c:110
#define DHCP_MIN_OPTION
Minimum normal DHCP option.
Definition: dhcp.h:63
const char * name
Name.
Definition: settings.h:29
int dhcp_create_packet(struct dhcp_packet *dhcppkt, struct net_device *netdev, uint8_t msgtype, uint32_t xid, const void *options, size_t options_len, void *data, size_t max_len)
Create a DHCP packet.
Definition: dhcp.c:945
static int copy_encap_settings(struct dhcp_packet *dest, struct settings *source, unsigned int encapsulator)
Copy settings to DHCP packet.
Definition: fakedhcp.c:51
uint64_t tag
Setting tag, if applicable.
Definition: settings.h:44
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define PROXYDHCP_SETTINGS_NAME
Settings block name used for ProxyDHCP responses.
Definition: dhcp.h:714
ring len
Length.
Definition: dwmac.h:231
static struct net_device * netdev
Definition: gdbudp.c:53
struct in_addr ciaddr
"Client" IP address
Definition: dhcp.h:644
#define PXEBS_SETTINGS_NAME
Setting block name used for BootServerDHCP responses.
Definition: dhcp.h:717
Configuration settings.
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
#define DHCPDISCOVER
Definition: dhcp.h:198
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
IP address structure.
Definition: in.h:42
A network device.
Definition: netdevice.h:353
int dhcppkt_store(struct dhcp_packet *dhcppkt, unsigned int tag, const void *data, size_t len)
Store value of DHCP packet setting.
Definition: dhcppkt.c:165
A settings block.
Definition: settings.h:133
#define DHCPACK
Definition: dhcp.h:202
A setting.
Definition: settings.h:24
Network device management.
uint32_t dhcp_last_xid
Most recent DHCP transaction ID.
Definition: dhcp.c:125
FILE_SECBOOT(PERMITTED)
struct dhcphdr * dhcphdr
The DHCP packet contents.
Definition: dhcppkt.h:25
struct settings * find_settings(const char *name)
Find settings block.
Definition: settings.c:407
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:151
uint8_t data[48]
Additional event data.
Definition: ena.h:22
DHCP packets.
#define DHCP_VENDOR_ENCAP
Vendor encapsulated options.
Definition: dhcp.h:93
#define DHCP_ENCAP_OPT(encapsulator, encapsulated)
Construct a tag value for an encapsulated option.
Definition: dhcp.h:41
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
uint64_t tag
Identity tag.
Definition: edd.h:31
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
String functions.
int create_fakepxebsack(struct net_device *netdev, void *data, size_t max_len)
Create fake PXE Boot Server ACK packet.
Definition: fakedhcp.c:179
Fake DHCP packets.