2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <gpxe/settings.h>
25 #include <gpxe/netdevice.h>
26 #include <gpxe/dhcppkt.h>
27 #include <gpxe/fakedhcp.h>
36 * Copy settings to DHCP packet
38 * @v dest Destination DHCP packet
39 * @v source Source settings block
40 * @v encapsulator Encapsulating setting tag number, or zero
41 * @ret rc Return status code
43 static int copy_encap_settings ( struct dhcp_packet *dest,
44 struct settings *source,
45 unsigned int encapsulator ) {
46 struct setting setting = { .name = "" };
53 for ( subtag = DHCP_MIN_OPTION; subtag <= DHCP_MAX_OPTION; subtag++ ) {
54 tag = DHCP_ENCAP_OPT ( encapsulator, subtag );
57 case DHCP_VENDOR_ENCAP:
58 /* Process encapsulated settings */
59 if ( ( rc = copy_encap_settings ( dest, source,
64 /* Copy setting, if present */
66 len = fetch_setting_len ( source, &setting );
72 check_len = fetch_setting ( source, &setting,
74 assert ( check_len == len );
75 if ( ( rc = dhcppkt_store ( dest, tag, buf,
87 * Copy settings to DHCP packet
89 * @v dest Destination DHCP packet
90 * @v source Source settings block
91 * @ret rc Return status code
93 static int copy_settings ( struct dhcp_packet *dest,
94 struct settings *source ) {
95 return copy_encap_settings ( dest, source, 0 );
99 * Create fake DHCPDISCOVER packet
101 * @v netdev Network device
102 * @v data Buffer for DHCP packet
103 * @v max_len Size of DHCP packet buffer
104 * @ret rc Return status code
106 * Used by external code.
108 int create_fakedhcpdiscover ( struct net_device *netdev,
109 void *data, size_t max_len ) {
110 struct dhcp_packet dhcppkt;
111 struct in_addr ciaddr = { 0 };
114 if ( ( rc = dhcp_create_request ( &dhcppkt, netdev, ciaddr, NULL, data,
116 DBG ( "Could not create DHCPDISCOVER: %s\n",
125 * Create fake DHCPACK packet
127 * @v netdev Network device
128 * @v data Buffer for DHCP packet
129 * @v max_len Size of DHCP packet buffer
130 * @ret rc Return status code
132 * Used by external code.
134 int create_fakedhcpack ( struct net_device *netdev,
135 void *data, size_t max_len ) {
136 struct dhcp_packet dhcppkt;
139 /* Create base DHCPACK packet */
140 if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL,
141 data, max_len ) ) != 0 ) {
142 DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) );
146 /* Merge in globally-scoped settings, then netdev-specific
147 * settings. Do it in this order so that netdev-specific
148 * settings take precedence regardless of stated priorities.
150 if ( ( rc = copy_settings ( &dhcppkt, NULL ) ) != 0 ) {
151 DBG ( "Could not set DHCPACK global settings: %s\n",
155 if ( ( rc = copy_settings ( &dhcppkt,
156 netdev_settings ( netdev ) ) ) != 0 ) {
157 DBG ( "Could not set DHCPACK netdev settings: %s\n",
166 * Create ProxyDHCPACK packet
168 * @v netdev Network device
169 * @v data Buffer for DHCP packet
170 * @v max_len Size of DHCP packet buffer
171 * @ret rc Return status code
173 * Used by external code.
175 int create_fakeproxydhcpack ( struct net_device *netdev,
176 void *data, size_t max_len ) {
177 struct dhcp_packet dhcppkt;
178 struct settings *settings;
181 /* Identify ProxyDHCP settings */
182 settings = find_settings ( PROXYDHCP_SETTINGS_NAME );
184 /* No ProxyDHCP settings => use normal DHCPACK */
186 return create_fakedhcpack ( netdev, data, max_len );
188 /* Create base DHCPACK packet */
189 if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL,
190 data, max_len ) ) != 0 ) {
191 DBG ( "Could not create ProxyDHCPACK: %s\n",
196 /* Merge in ProxyDHCP options */
197 if ( ( rc = copy_settings ( &dhcppkt, settings ) ) != 0 ) {
198 DBG ( "Could not set ProxyDHCPACK settings: %s\n",