|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2008 Michael Brown <[email protected]>. ! 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., 675 Mass Ave, Cambridge, MA 02139, USA. ! 17: */ ! 18: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: #include <stdint.h> ! 22: #include <stdlib.h> ! 23: #include <stdio.h> ! 24: #include <errno.h> ! 25: #include <string.h> ! 26: #include <ipxe/settings.h> ! 27: #include <ipxe/netdevice.h> ! 28: #include <ipxe/dhcppkt.h> ! 29: #include <ipxe/fakedhcp.h> ! 30: ! 31: /** @file ! 32: * ! 33: * Fake DHCP packets ! 34: * ! 35: */ ! 36: ! 37: /** ! 38: * Copy settings to DHCP packet ! 39: * ! 40: * @v dest Destination DHCP packet ! 41: * @v source Source settings block ! 42: * @v encapsulator Encapsulating setting tag number, or zero ! 43: * @ret rc Return status code ! 44: */ ! 45: static int copy_encap_settings ( struct dhcp_packet *dest, ! 46: struct settings *source, ! 47: unsigned int encapsulator ) { ! 48: struct setting setting = { .name = "" }; ! 49: unsigned int subtag; ! 50: unsigned int tag; ! 51: int len; ! 52: int check_len; ! 53: int rc; ! 54: ! 55: for ( subtag = DHCP_MIN_OPTION; subtag <= DHCP_MAX_OPTION; subtag++ ) { ! 56: tag = DHCP_ENCAP_OPT ( encapsulator, subtag ); ! 57: switch ( tag ) { ! 58: case DHCP_EB_ENCAP: ! 59: case DHCP_VENDOR_ENCAP: ! 60: /* Process encapsulated settings */ ! 61: if ( ( rc = copy_encap_settings ( dest, source, ! 62: tag ) ) != 0 ) ! 63: return rc; ! 64: break; ! 65: default: ! 66: /* Copy setting, if present */ ! 67: setting.tag = tag; ! 68: len = fetch_setting_len ( source, &setting ); ! 69: if ( len < 0 ) ! 70: break; ! 71: { ! 72: char buf[len]; ! 73: ! 74: check_len = fetch_setting ( source, &setting, ! 75: buf, sizeof (buf)); ! 76: assert ( check_len == len ); ! 77: if ( ( rc = dhcppkt_store ( dest, tag, buf, ! 78: sizeof(buf) )) !=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: */ ! 110: int create_fakedhcpdiscover ( struct net_device *netdev, ! 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: ciaddr, data, max_len ) ) != 0 ) { ! 118: DBG ( "Could not create DHCPDISCOVER: %s\n", ! 119: strerror ( rc ) ); ! 120: return rc; ! 121: } ! 122: ! 123: return 0; ! 124: } ! 125: ! 126: /** ! 127: * Create fake DHCPACK packet ! 128: * ! 129: * @v netdev Network device ! 130: * @v data Buffer for DHCP packet ! 131: * @v max_len Size of DHCP packet buffer ! 132: * @ret rc Return status code ! 133: * ! 134: * Used by external code. ! 135: */ ! 136: int create_fakedhcpack ( struct net_device *netdev, ! 137: void *data, size_t max_len ) { ! 138: struct dhcp_packet dhcppkt; ! 139: int rc; ! 140: ! 141: /* Create base DHCPACK packet */ ! 142: if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0, ! 143: data, max_len ) ) != 0 ) { ! 144: DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) ); ! 145: return rc; ! 146: } ! 147: ! 148: /* Merge in globally-scoped settings, then netdev-specific ! 149: * settings. Do it in this order so that netdev-specific ! 150: * settings take precedence regardless of stated priorities. ! 151: */ ! 152: if ( ( rc = copy_settings ( &dhcppkt, NULL ) ) != 0 ) { ! 153: DBG ( "Could not set DHCPACK global settings: %s\n", ! 154: strerror ( rc ) ); ! 155: return rc; ! 156: } ! 157: if ( ( rc = copy_settings ( &dhcppkt, ! 158: netdev_settings ( netdev ) ) ) != 0 ) { ! 159: DBG ( "Could not set DHCPACK netdev settings: %s\n", ! 160: strerror ( rc ) ); ! 161: return rc; ! 162: } ! 163: ! 164: return 0; ! 165: } ! 166: ! 167: /** ! 168: * Create fake PXE Boot Server ACK packet ! 169: * ! 170: * @v netdev Network device ! 171: * @v data Buffer for DHCP packet ! 172: * @v max_len Size of DHCP packet buffer ! 173: * @ret rc Return status code ! 174: * ! 175: * Used by external code. ! 176: */ ! 177: int create_fakepxebsack ( struct net_device *netdev, ! 178: void *data, size_t max_len ) { ! 179: struct dhcp_packet dhcppkt; ! 180: struct settings *proxy_settings; ! 181: struct settings *pxebs_settings; ! 182: int rc; ! 183: ! 184: /* Identify available settings */ ! 185: proxy_settings = find_settings ( PROXYDHCP_SETTINGS_NAME ); ! 186: pxebs_settings = find_settings ( PXEBS_SETTINGS_NAME ); ! 187: if ( ( ! proxy_settings ) && ( ! pxebs_settings ) ) { ! 188: /* No PXE boot server; return the regular DHCPACK */ ! 189: return create_fakedhcpack ( netdev, data, max_len ); ! 190: } ! 191: ! 192: /* Create base DHCPACK packet */ ! 193: if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0, ! 194: data, max_len ) ) != 0 ) { ! 195: DBG ( "Could not create PXE BS ACK: %s\n", ! 196: strerror ( rc ) ); ! 197: return rc; ! 198: } ! 199: ! 200: /* Merge in ProxyDHCP options */ ! 201: if ( proxy_settings && ! 202: ( ( rc = copy_settings ( &dhcppkt, proxy_settings ) ) != 0 ) ) { ! 203: DBG ( "Could not copy ProxyDHCP settings: %s\n", ! 204: strerror ( rc ) ); ! 205: return rc; ! 206: } ! 207: ! 208: /* Merge in BootServerDHCP options, if present */ ! 209: if ( pxebs_settings && ! 210: ( ( rc = copy_settings ( &dhcppkt, pxebs_settings ) ) != 0 ) ) { ! 211: DBG ( "Could not copy PXE BS settings: %s\n", ! 212: strerror ( rc ) ); ! 213: return rc; ! 214: } ! 215: ! 216: return 0; ! 217: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.