00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <stdint.h>
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <errno.h>
00025 #include <string.h>
00026 #include <gpxe/settings.h>
00027 #include <gpxe/netdevice.h>
00028 #include <gpxe/dhcppkt.h>
00029 #include <gpxe/fakedhcp.h>
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 static int copy_encap_settings ( struct dhcp_packet *dest,
00046 struct settings *source,
00047 unsigned int encapsulator ) {
00048 struct setting setting = { .name = "" };
00049 unsigned int subtag;
00050 unsigned int tag;
00051 int len;
00052 int check_len;
00053 int rc;
00054
00055 for ( subtag = DHCP_MIN_OPTION; subtag <= DHCP_MAX_OPTION; subtag++ ) {
00056 tag = DHCP_ENCAP_OPT ( encapsulator, subtag );
00057 switch ( tag ) {
00058 case DHCP_EB_ENCAP:
00059 case DHCP_VENDOR_ENCAP:
00060
00061 if ( ( rc = copy_encap_settings ( dest, source,
00062 tag ) ) != 0 )
00063 return rc;
00064 break;
00065 default:
00066
00067 setting.tag = tag;
00068 len = fetch_setting_len ( source, &setting );
00069 if ( len < 0 )
00070 break;
00071 {
00072 char buf[len];
00073
00074 check_len = fetch_setting ( source, &setting,
00075 buf, sizeof (buf));
00076 assert ( check_len == len );
00077 if ( ( rc = dhcppkt_store ( dest, tag, buf,
00078 sizeof(buf) )) !=0)
00079 return rc;
00080 }
00081 break;
00082 }
00083 }
00084
00085 return 0;
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095 static int copy_settings ( struct dhcp_packet *dest,
00096 struct settings *source ) {
00097 return copy_encap_settings ( dest, source, 0 );
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 int create_fakedhcpdiscover ( struct net_device *netdev,
00111 void *data, size_t max_len ) {
00112 struct dhcp_packet dhcppkt;
00113 struct in_addr ciaddr = { 0 };
00114 int rc;
00115
00116 if ( ( rc = dhcp_create_request ( &dhcppkt, netdev, DHCPDISCOVER,
00117 ciaddr, data, max_len ) ) != 0 ) {
00118 DBG ( "Could not create DHCPDISCOVER: %s\n",
00119 strerror ( rc ) );
00120 return rc;
00121 }
00122
00123 return 0;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 int create_fakedhcpack ( struct net_device *netdev,
00137 void *data, size_t max_len ) {
00138 struct dhcp_packet dhcppkt;
00139 int rc;
00140
00141
00142 if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0,
00143 data, max_len ) ) != 0 ) {
00144 DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) );
00145 return rc;
00146 }
00147
00148
00149
00150
00151
00152 if ( ( rc = copy_settings ( &dhcppkt, NULL ) ) != 0 ) {
00153 DBG ( "Could not set DHCPACK global settings: %s\n",
00154 strerror ( rc ) );
00155 return rc;
00156 }
00157 if ( ( rc = copy_settings ( &dhcppkt,
00158 netdev_settings ( netdev ) ) ) != 0 ) {
00159 DBG ( "Could not set DHCPACK netdev settings: %s\n",
00160 strerror ( rc ) );
00161 return rc;
00162 }
00163
00164 return 0;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 int create_fakepxebsack ( struct net_device *netdev,
00178 void *data, size_t max_len ) {
00179 struct dhcp_packet dhcppkt;
00180 struct settings *proxy_settings;
00181 struct settings *pxebs_settings;
00182 int rc;
00183
00184
00185 proxy_settings = find_settings ( PROXYDHCP_SETTINGS_NAME );
00186 pxebs_settings = find_settings ( PXEBS_SETTINGS_NAME );
00187 if ( ( ! proxy_settings ) && ( ! pxebs_settings ) ) {
00188
00189 return create_fakedhcpack ( netdev, data, max_len );
00190 }
00191
00192
00193 if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0,
00194 data, max_len ) ) != 0 ) {
00195 DBG ( "Could not create PXE BS ACK: %s\n",
00196 strerror ( rc ) );
00197 return rc;
00198 }
00199
00200
00201 if ( proxy_settings &&
00202 ( ( rc = copy_settings ( &dhcppkt, proxy_settings ) ) != 0 ) ) {
00203 DBG ( "Could not copy ProxyDHCP settings: %s\n",
00204 strerror ( rc ) );
00205 return rc;
00206 }
00207
00208
00209 if ( pxebs_settings &&
00210 ( ( rc = copy_settings ( &dhcppkt, pxebs_settings ) ) != 0 ) ) {
00211 DBG ( "Could not copy PXE BS settings: %s\n",
00212 strerror ( rc ) );
00213 return rc;
00214 }
00215
00216 return 0;
00217 }