00001 /** @file 00002 * 00003 * PXE UDP API 00004 * 00005 */ 00006 00007 #include <string.h> 00008 #include <byteswap.h> 00009 #include <gpxe/xfer.h> 00010 #include <gpxe/udp.h> 00011 #include <gpxe/uaccess.h> 00012 #include <gpxe/process.h> 00013 #include <pxe.h> 00014 00015 /* 00016 * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>. 00017 * 00018 * This program is free software; you can redistribute it and/or 00019 * modify it under the terms of the GNU General Public License as 00020 * published by the Free Software Foundation; either version 2 of the 00021 * License, or any later version. 00022 * 00023 * This program is distributed in the hope that it will be useful, but 00024 * WITHOUT ANY WARRANTY; without even the implied warranty of 00025 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00026 * General Public License for more details. 00027 * 00028 * You should have received a copy of the GNU General Public License 00029 * along with this program; if not, write to the Free Software 00030 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00031 */ 00032 00033 FILE_LICENCE ( GPL2_OR_LATER ); 00034 00035 /** A PXE UDP connection */ 00036 struct pxe_udp_connection { 00037 /** Data transfer interface to UDP stack */ 00038 struct xfer_interface xfer; 00039 /** Local address */ 00040 struct sockaddr_in local; 00041 /** Current PXENV_UDP_READ parameter block */ 00042 struct s_PXENV_UDP_READ *pxenv_udp_read; 00043 }; 00044 00045 /** 00046 * Receive PXE UDP data 00047 * 00048 * @v xfer Data transfer interface 00049 * @v iobuf I/O buffer 00050 * @v meta Data transfer metadata 00051 * @ret rc Return status code 00052 * 00053 * Receives a packet as part of the current pxenv_udp_read() 00054 * operation. 00055 */ 00056 static int pxe_udp_deliver_iob ( struct xfer_interface *xfer, 00057 struct io_buffer *iobuf, 00058 struct xfer_metadata *meta ) { 00059 struct pxe_udp_connection *pxe_udp = 00060 container_of ( xfer, struct pxe_udp_connection, xfer ); 00061 struct s_PXENV_UDP_READ *pxenv_udp_read = pxe_udp->pxenv_udp_read; 00062 struct sockaddr_in *sin_src; 00063 struct sockaddr_in *sin_dest; 00064 userptr_t buffer; 00065 size_t len; 00066 int rc = 0; 00067 00068 if ( ! pxenv_udp_read ) { 00069 DBG ( "PXE discarded UDP packet\n" ); 00070 rc = -ENOBUFS; 00071 goto done; 00072 } 00073 00074 /* Copy packet to buffer and record length */ 00075 buffer = real_to_user ( pxenv_udp_read->buffer.segment, 00076 pxenv_udp_read->buffer.offset ); 00077 len = iob_len ( iobuf ); 00078 if ( len > pxenv_udp_read->buffer_size ) 00079 len = pxenv_udp_read->buffer_size; 00080 copy_to_user ( buffer, 0, iobuf->data, len ); 00081 pxenv_udp_read->buffer_size = len; 00082 00083 /* Fill in source/dest information */ 00084 assert ( meta ); 00085 sin_src = ( struct sockaddr_in * ) meta->src; 00086 assert ( sin_src ); 00087 assert ( sin_src->sin_family == AF_INET ); 00088 pxenv_udp_read->src_ip = sin_src->sin_addr.s_addr; 00089 pxenv_udp_read->s_port = sin_src->sin_port; 00090 sin_dest = ( struct sockaddr_in * ) meta->dest; 00091 assert ( sin_dest ); 00092 assert ( sin_dest->sin_family == AF_INET ); 00093 pxenv_udp_read->dest_ip = sin_dest->sin_addr.s_addr; 00094 pxenv_udp_read->d_port = sin_dest->sin_port; 00095 00096 /* Mark as received */ 00097 pxe_udp->pxenv_udp_read = NULL; 00098 00099 done: 00100 free_iob ( iobuf ); 00101 return rc; 00102 } 00103 00104 /** PXE UDP data transfer interface operations */ 00105 static struct xfer_interface_operations pxe_udp_xfer_operations = { 00106 .close = ignore_xfer_close, 00107 .vredirect = ignore_xfer_vredirect, 00108 .window = unlimited_xfer_window, 00109 .alloc_iob = default_xfer_alloc_iob, 00110 .deliver_iob = pxe_udp_deliver_iob, 00111 .deliver_raw = xfer_deliver_as_iob, 00112 }; 00113 00114 /** The PXE UDP connection */ 00115 static struct pxe_udp_connection pxe_udp = { 00116 .xfer = XFER_INIT ( &pxe_udp_xfer_operations ), 00117 .local = { 00118 .sin_family = AF_INET, 00119 }, 00120 }; 00121 00122 /** 00123 * UDP OPEN 00124 * 00125 * @v pxenv_udp_open Pointer to a struct s_PXENV_UDP_OPEN 00126 * @v s_PXENV_UDP_OPEN::src_ip IP address of this station, or 0.0.0.0 00127 * @ret #PXENV_EXIT_SUCCESS Always 00128 * @ret s_PXENV_UDP_OPEN::Status PXE status code 00129 * @err #PXENV_STATUS_UDP_OPEN UDP connection already open 00130 * @err #PXENV_STATUS_OUT_OF_RESOURCES Could not open connection 00131 * 00132 * Prepares the PXE stack for communication using pxenv_udp_write() 00133 * and pxenv_udp_read(). 00134 * 00135 * The IP address supplied in s_PXENV_UDP_OPEN::src_ip will be 00136 * recorded and used as the local station's IP address for all further 00137 * communication, including communication by means other than 00138 * pxenv_udp_write() and pxenv_udp_read(). (If 00139 * s_PXENV_UDP_OPEN::src_ip is 0.0.0.0, the local station's IP address 00140 * will remain unchanged.) 00141 * 00142 * You can only have one open UDP connection at a time. This is not a 00143 * meaningful restriction, since pxenv_udp_write() and 00144 * pxenv_udp_read() allow you to specify arbitrary local and remote 00145 * ports and an arbitrary remote address for each packet. According 00146 * to the PXE specifiation, you cannot have a UDP connection open at 00147 * the same time as a TFTP connection; this restriction does not apply 00148 * to Etherboot. 00149 * 00150 * On x86, you must set the s_PXE::StatusCallout field to a nonzero 00151 * value before calling this function in protected mode. You cannot 00152 * call this function with a 32-bit stack segment. (See the relevant 00153 * @ref pxe_x86_pmode16 "implementation note" for more details.) 00154 * 00155 * @note The PXE specification does not make it clear whether the IP 00156 * address supplied in s_PXENV_UDP_OPEN::src_ip should be used only 00157 * for this UDP connection, or retained for all future communication. 00158 * The latter seems more consistent with typical PXE stack behaviour. 00159 * 00160 * @note Etherboot currently ignores the s_PXENV_UDP_OPEN::src_ip 00161 * parameter. 00162 * 00163 */ 00164 PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) { 00165 int rc; 00166 00167 DBG ( "PXENV_UDP_OPEN" ); 00168 00169 /* Record source IP address */ 00170 pxe_udp.local.sin_addr.s_addr = pxenv_udp_open->src_ip; 00171 DBG ( " %s", inet_ntoa ( pxe_udp.local.sin_addr ) ); 00172 00173 /* Open promiscuous UDP connection */ 00174 xfer_close ( &pxe_udp.xfer, 0 ); 00175 if ( ( rc = udp_open_promisc ( &pxe_udp.xfer ) ) != 0 ) { 00176 pxenv_udp_open->Status = PXENV_STATUS ( rc ); 00177 return PXENV_EXIT_FAILURE; 00178 } 00179 00180 pxenv_udp_open->Status = PXENV_STATUS_SUCCESS; 00181 return PXENV_EXIT_SUCCESS; 00182 } 00183 00184 /** 00185 * UDP CLOSE 00186 * 00187 * @v pxenv_udp_close Pointer to a struct s_PXENV_UDP_CLOSE 00188 * @ret #PXENV_EXIT_SUCCESS Always 00189 * @ret s_PXENV_UDP_CLOSE::Status PXE status code 00190 * @err None - 00191 * 00192 * Closes a UDP connection opened with pxenv_udp_open(). 00193 * 00194 * You can only have one open UDP connection at a time. You cannot 00195 * have a UDP connection open at the same time as a TFTP connection. 00196 * You cannot use pxenv_udp_close() to close a TFTP connection; use 00197 * pxenv_tftp_close() instead. 00198 * 00199 * On x86, you must set the s_PXE::StatusCallout field to a nonzero 00200 * value before calling this function in protected mode. You cannot 00201 * call this function with a 32-bit stack segment. (See the relevant 00202 * @ref pxe_x86_pmode16 "implementation note" for more details.) 00203 * 00204 */ 00205 PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) { 00206 DBG ( "PXENV_UDP_CLOSE" ); 00207 00208 /* Close UDP connection */ 00209 xfer_close ( &pxe_udp.xfer, 0 ); 00210 00211 pxenv_udp_close->Status = PXENV_STATUS_SUCCESS; 00212 return PXENV_EXIT_SUCCESS; 00213 } 00214 00215 /** 00216 * UDP WRITE 00217 * 00218 * @v pxenv_udp_write Pointer to a struct s_PXENV_UDP_WRITE 00219 * @v s_PXENV_UDP_WRITE::ip Destination IP address 00220 * @v s_PXENV_UDP_WRITE::gw Relay agent IP address, or 0.0.0.0 00221 * @v s_PXENV_UDP_WRITE::src_port Source UDP port, or 0 00222 * @v s_PXENV_UDP_WRITE::dst_port Destination UDP port 00223 * @v s_PXENV_UDP_WRITE::buffer_size Length of the UDP payload 00224 * @v s_PXENV_UDP_WRITE::buffer Address of the UDP payload 00225 * @ret #PXENV_EXIT_SUCCESS Packet was transmitted successfully 00226 * @ret #PXENV_EXIT_FAILURE Packet could not be transmitted 00227 * @ret s_PXENV_UDP_WRITE::Status PXE status code 00228 * @err #PXENV_STATUS_UDP_CLOSED UDP connection is not open 00229 * @err #PXENV_STATUS_UNDI_TRANSMIT_ERROR Could not transmit packet 00230 * 00231 * Transmits a single UDP packet. A valid IP and UDP header will be 00232 * prepended to the payload in s_PXENV_UDP_WRITE::buffer; the buffer 00233 * should not contain precomputed IP and UDP headers, nor should it 00234 * contain space allocated for these headers. The first byte of the 00235 * buffer will be transmitted as the first byte following the UDP 00236 * header. 00237 * 00238 * If s_PXENV_UDP_WRITE::gw is 0.0.0.0, normal IP routing will take 00239 * place. See the relevant @ref pxe_routing "implementation note" for 00240 * more details. 00241 * 00242 * If s_PXENV_UDP_WRITE::src_port is 0, port 2069 will be used. 00243 * 00244 * You must have opened a UDP connection with pxenv_udp_open() before 00245 * calling pxenv_udp_write(). 00246 * 00247 * On x86, you must set the s_PXE::StatusCallout field to a nonzero 00248 * value before calling this function in protected mode. You cannot 00249 * call this function with a 32-bit stack segment. (See the relevant 00250 * @ref pxe_x86_pmode16 "implementation note" for more details.) 00251 * 00252 * @note Etherboot currently ignores the s_PXENV_UDP_WRITE::gw 00253 * parameter. 00254 * 00255 */ 00256 PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) { 00257 struct sockaddr_in dest; 00258 struct xfer_metadata meta = { 00259 .src = ( struct sockaddr * ) &pxe_udp.local, 00260 .dest = ( struct sockaddr * ) &dest, 00261 .netdev = pxe_netdev, 00262 }; 00263 size_t len; 00264 struct io_buffer *iobuf; 00265 userptr_t buffer; 00266 int rc; 00267 00268 DBG ( "PXENV_UDP_WRITE" ); 00269 00270 /* Construct destination socket address */ 00271 memset ( &dest, 0, sizeof ( dest ) ); 00272 dest.sin_family = AF_INET; 00273 dest.sin_addr.s_addr = pxenv_udp_write->ip; 00274 dest.sin_port = pxenv_udp_write->dst_port; 00275 00276 /* Set local (source) port. PXE spec says source port is 2069 00277 * if not specified. Really, this ought to be set at UDP open 00278 * time but hey, we didn't design this API. 00279 */ 00280 pxe_udp.local.sin_port = pxenv_udp_write->src_port; 00281 if ( ! pxe_udp.local.sin_port ) 00282 pxe_udp.local.sin_port = htons ( 2069 ); 00283 00284 /* FIXME: we ignore the gateway specified, since we're 00285 * confident of being able to do our own routing. We should 00286 * probably allow for multiple gateways. 00287 */ 00288 00289 /* Allocate and fill data buffer */ 00290 len = pxenv_udp_write->buffer_size; 00291 iobuf = xfer_alloc_iob ( &pxe_udp.xfer, len ); 00292 if ( ! iobuf ) { 00293 pxenv_udp_write->Status = PXENV_STATUS_OUT_OF_RESOURCES; 00294 return PXENV_EXIT_FAILURE; 00295 } 00296 buffer = real_to_user ( pxenv_udp_write->buffer.segment, 00297 pxenv_udp_write->buffer.offset ); 00298 copy_from_user ( iob_put ( iobuf, len ), buffer, 0, len ); 00299 00300 DBG ( " %04x:%04x+%x %d->%s:%d", pxenv_udp_write->buffer.segment, 00301 pxenv_udp_write->buffer.offset, pxenv_udp_write->buffer_size, 00302 ntohs ( pxenv_udp_write->src_port ), 00303 inet_ntoa ( dest.sin_addr ), 00304 ntohs ( pxenv_udp_write->dst_port ) ); 00305 00306 /* Transmit packet */ 00307 if ( ( rc = xfer_deliver_iob_meta ( &pxe_udp.xfer, iobuf, 00308 &meta ) ) != 0 ) { 00309 pxenv_udp_write->Status = PXENV_STATUS ( rc ); 00310 return PXENV_EXIT_FAILURE; 00311 } 00312 00313 pxenv_udp_write->Status = PXENV_STATUS_SUCCESS; 00314 return PXENV_EXIT_SUCCESS; 00315 } 00316 00317 /** 00318 * UDP READ 00319 * 00320 * @v pxenv_udp_read Pointer to a struct s_PXENV_UDP_READ 00321 * @v s_PXENV_UDP_READ::dest_ip Destination IP address, or 0.0.0.0 00322 * @v s_PXENV_UDP_READ::d_port Destination UDP port, or 0 00323 * @v s_PXENV_UDP_READ::buffer_size Size of the UDP payload buffer 00324 * @v s_PXENV_UDP_READ::buffer Address of the UDP payload buffer 00325 * @ret #PXENV_EXIT_SUCCESS A packet has been received 00326 * @ret #PXENV_EXIT_FAILURE No packet has been received 00327 * @ret s_PXENV_UDP_READ::Status PXE status code 00328 * @ret s_PXENV_UDP_READ::src_ip Source IP address 00329 * @ret s_PXENV_UDP_READ::dest_ip Destination IP address 00330 * @ret s_PXENV_UDP_READ::s_port Source UDP port 00331 * @ret s_PXENV_UDP_READ::d_port Destination UDP port 00332 * @ret s_PXENV_UDP_READ::buffer_size Length of UDP payload 00333 * @err #PXENV_STATUS_UDP_CLOSED UDP connection is not open 00334 * @err #PXENV_STATUS_FAILURE No packet was ready to read 00335 * 00336 * Receive a single UDP packet. This is a non-blocking call; if no 00337 * packet is ready to read, the call will return instantly with 00338 * s_PXENV_UDP_READ::Status==PXENV_STATUS_FAILURE. 00339 * 00340 * If s_PXENV_UDP_READ::dest_ip is 0.0.0.0, UDP packets addressed to 00341 * any IP address will be accepted and may be returned to the caller. 00342 * 00343 * If s_PXENV_UDP_READ::d_port is 0, UDP packets addressed to any UDP 00344 * port will be accepted and may be returned to the caller. 00345 * 00346 * You must have opened a UDP connection with pxenv_udp_open() before 00347 * calling pxenv_udp_read(). 00348 * 00349 * On x86, you must set the s_PXE::StatusCallout field to a nonzero 00350 * value before calling this function in protected mode. You cannot 00351 * call this function with a 32-bit stack segment. (See the relevant 00352 * @ref pxe_x86_pmode16 "implementation note" for more details.) 00353 * 00354 * @note The PXE specification (version 2.1) does not state that we 00355 * should fill in s_PXENV_UDP_READ::dest_ip and 00356 * s_PXENV_UDP_READ::d_port, but Microsoft Windows' NTLDR program 00357 * expects us to do so, and will fail if we don't. 00358 * 00359 */ 00360 PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) { 00361 struct in_addr dest_ip_wanted = { .s_addr = pxenv_udp_read->dest_ip }; 00362 struct in_addr dest_ip; 00363 uint16_t d_port_wanted = pxenv_udp_read->d_port; 00364 uint16_t d_port; 00365 00366 DBG ( "PXENV_UDP_READ" ); 00367 00368 /* Try receiving a packet */ 00369 pxe_udp.pxenv_udp_read = pxenv_udp_read; 00370 step(); 00371 if ( pxe_udp.pxenv_udp_read ) { 00372 /* No packet received */ 00373 pxe_udp.pxenv_udp_read = NULL; 00374 goto no_packet; 00375 } 00376 dest_ip.s_addr = pxenv_udp_read->dest_ip; 00377 d_port = pxenv_udp_read->d_port; 00378 00379 /* Filter on destination address and/or port */ 00380 if ( dest_ip_wanted.s_addr && 00381 ( dest_ip_wanted.s_addr != dest_ip.s_addr ) ) { 00382 DBG ( " wrong IP %s", inet_ntoa ( dest_ip ) ); 00383 DBG ( " (wanted %s)", inet_ntoa ( dest_ip_wanted ) ); 00384 goto no_packet; 00385 } 00386 if ( d_port_wanted && ( d_port_wanted != d_port ) ) { 00387 DBG ( " wrong port %d ", htons ( d_port ) ); 00388 DBG ( " (wanted %d)", htons ( d_port_wanted ) ); 00389 goto no_packet; 00390 } 00391 00392 DBG ( " %04x:%04x+%x %s:", pxenv_udp_read->buffer.segment, 00393 pxenv_udp_read->buffer.offset, pxenv_udp_read->buffer_size, 00394 inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->src_ip ) )); 00395 DBG ( "%d<-%s:%d", ntohs ( pxenv_udp_read->s_port ), 00396 inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->dest_ip ) ), 00397 ntohs ( pxenv_udp_read->d_port ) ); 00398 00399 pxenv_udp_read->Status = PXENV_STATUS_SUCCESS; 00400 return PXENV_EXIT_SUCCESS; 00401 00402 no_packet: 00403 pxenv_udp_read->Status = PXENV_STATUS_FAILURE; 00404 return PXENV_EXIT_FAILURE; 00405 }
1.5.7.1