Updated TFTP and PXE UDP API code to use not-yet-implemented data-xfer
[people/dverkamp/gpxe.git] / src / interface / pxe / pxe_udp.c
1 /** @file
2  *
3  * PXE UDP API
4  *
5  */
6
7 #include <string.h>
8 #include <byteswap.h>
9 #include <gpxe/xfer.h>
10 #include <gpxe/udp.h>
11 #include <gpxe/uaccess.h>
12 #include <gpxe/process.h>
13 #include <pxe.h>
14
15 /*
16  * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
17  *
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License as
20  * published by the Free Software Foundation; either version 2 of the
21  * License, or any later version.
22  *
23  * This program is distributed in the hope that it will be useful, but
24  * WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26  * General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31  */
32
33 /** A PXE UDP connection */
34 struct pxe_udp_connection {
35         /** Data transfer interface to UDP stack */
36         struct xfer_interface xfer;
37         /** "Connection is open" flag */
38         int open;
39         /** Local address */
40         struct sockaddr_in local;
41         /** Current PXENV_UDP_READ parameter block */
42         struct s_PXENV_UDP_READ *pxenv_udp_read;
43 };
44
45 /**
46  * Receive PXE UDP data
47  *
48  * @v xfer                      Data transfer interface
49  * @v iobuf                     I/O buffer
50  * @v meta                      Data transfer metadata
51  * @ret rc                      Return status code
52  *
53  * Receives a packet as part of the current pxenv_udp_read()
54  * operation.
55  */
56 static int pxe_udp_deliver_iob ( struct xfer_interface *xfer,
57                                  struct io_buffer *iobuf,
58                                  struct xfer_metadata *meta ) {
59         struct pxe_udp_connection *pxe_udp = 
60                 container_of ( xfer, struct pxe_udp_connection, xfer );
61         struct s_PXENV_UDP_READ *pxenv_udp_read = pxe_udp->pxenv_udp_read;
62         struct sockaddr_in *sin_src;
63         struct sockaddr_in *sin_dest;
64         userptr_t buffer;
65         size_t len;
66         int rc = 0;
67
68         if ( ! pxenv_udp_read ) {
69                 DBG ( "PXE discarded UDP packet\n" );
70                 rc = -ENOBUFS;
71                 goto done;
72         }
73
74         /* Copy packet to buffer and record length */
75         buffer = real_to_user ( pxenv_udp_read->buffer.segment,
76                                 pxenv_udp_read->buffer.offset );
77         len = iob_len ( iobuf );
78         if ( len > pxenv_udp_read->buffer_size )
79                 len = pxenv_udp_read->buffer_size;
80         copy_to_user ( buffer, 0, iobuf->data, len );
81         pxenv_udp_read->buffer_size = len;
82
83         /* Fill in source/dest information */
84         assert ( meta );
85         sin_src = ( struct sockaddr_in * ) meta->src;
86         assert ( sin_src );
87         assert ( sin_src->sin_family == AF_INET );
88         pxenv_udp_read->src_ip = sin_src->sin_addr.s_addr;
89         pxenv_udp_read->s_port = sin_src->sin_port;
90         sin_dest = ( struct sockaddr_in * ) meta->dest;
91         assert ( sin_dest );
92         assert ( sin_dest->sin_family == AF_INET );
93         pxenv_udp_read->dest_ip = sin_dest->sin_addr.s_addr;
94         pxenv_udp_read->d_port = sin_dest->sin_port;
95
96         /* Mark as received */
97         pxe_udp->pxenv_udp_read = NULL;
98
99  done:
100         free_iob ( iobuf );
101         return rc;
102 }
103
104 /** PXE UDP data transfer interface operations */
105 static struct xfer_interface_operations pxe_udp_xfer_operations = {
106         .close          = ignore_xfer_close,
107         .vredirect      = ignore_xfer_vredirect,
108         .request        = ignore_xfer_request,
109         .seek           = ignore_xfer_seek,
110         .alloc_iob      = default_xfer_alloc_iob,
111         .deliver_iob    = pxe_udp_deliver_iob,
112         .deliver_raw    = xfer_deliver_as_iob,
113 };
114
115 /** The PXE UDP connection */
116 static struct pxe_udp_connection pxe_udp = {
117         .xfer = {
118                 .intf = {
119                         .dest = &null_xfer.intf,
120                         .refcnt = NULL,
121                 },
122                 .op = &pxe_udp_xfer_operations,
123         },
124         .local = {
125                 .sin_family = AF_INET,
126         },
127 };
128
129 /**
130  * UDP OPEN
131  *
132  * @v pxenv_udp_open                    Pointer to a struct s_PXENV_UDP_OPEN
133  * @v s_PXENV_UDP_OPEN::src_ip          IP address of this station, or 0.0.0.0
134  * @ret #PXENV_EXIT_SUCCESS             Always
135  * @ret s_PXENV_UDP_OPEN::Status        PXE status code
136  * @err #PXENV_STATUS_UDP_OPEN          UDP connection already open
137  * @err #PXENV_STATUS_OUT_OF_RESOURCES  Could not open connection
138  *
139  * Prepares the PXE stack for communication using pxenv_udp_write()
140  * and pxenv_udp_read().
141  *
142  * The IP address supplied in s_PXENV_UDP_OPEN::src_ip will be
143  * recorded and used as the local station's IP address for all further
144  * communication, including communication by means other than
145  * pxenv_udp_write() and pxenv_udp_read().  (If
146  * s_PXENV_UDP_OPEN::src_ip is 0.0.0.0, the local station's IP address
147  * will remain unchanged.)
148  *
149  * You can only have one open UDP connection at a time.  This is not a
150  * meaningful restriction, since pxenv_udp_write() and
151  * pxenv_udp_read() allow you to specify arbitrary local and remote
152  * ports and an arbitrary remote address for each packet.  According
153  * to the PXE specifiation, you cannot have a UDP connection open at
154  * the same time as a TFTP connection; this restriction does not apply
155  * to Etherboot.
156  *
157  * On x86, you must set the s_PXE::StatusCallout field to a nonzero
158  * value before calling this function in protected mode.  You cannot
159  * call this function with a 32-bit stack segment.  (See the relevant
160  * @ref pxe_x86_pmode16 "implementation note" for more details.)
161  *
162  * @note The PXE specification does not make it clear whether the IP
163  * address supplied in s_PXENV_UDP_OPEN::src_ip should be used only
164  * for this UDP connection, or retained for all future communication.
165  * The latter seems more consistent with typical PXE stack behaviour.
166  *
167  * @note Etherboot currently ignores the s_PXENV_UDP_OPEN::src_ip
168  * parameter.
169  *
170  */
171 PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) {
172
173         DBG ( "PXENV_UDP_OPEN" );
174
175         /* Check connection is not already open */
176         if ( pxe_udp.open ) {
177                 pxenv_udp_open->Status = PXENV_STATUS_UDP_OPEN;
178                 return PXENV_EXIT_FAILURE;
179         }
180
181         /* Record source IP address */
182         pxe_udp.local.sin_addr.s_addr = pxenv_udp_open->src_ip;
183
184         /* Open promiscuous UDP connection */
185         udp_open_promisc ( &pxe_udp.xfer );
186         pxe_udp.open = 1;
187
188         pxenv_udp_open->Status = PXENV_STATUS_SUCCESS;
189         return PXENV_EXIT_SUCCESS;
190 }
191
192 /**
193  * UDP CLOSE
194  *
195  * @v pxenv_udp_close                   Pointer to a struct s_PXENV_UDP_CLOSE
196  * @ret #PXENV_EXIT_SUCCESS             Always
197  * @ret s_PXENV_UDP_CLOSE::Status       PXE status code
198  * @err None                            -
199  *
200  * Closes a UDP connection opened with pxenv_udp_open().
201  *
202  * You can only have one open UDP connection at a time.  You cannot
203  * have a UDP connection open at the same time as a TFTP connection.
204  * You cannot use pxenv_udp_close() to close a TFTP connection; use
205  * pxenv_tftp_close() instead.
206  *
207  * On x86, you must set the s_PXE::StatusCallout field to a nonzero
208  * value before calling this function in protected mode.  You cannot
209  * call this function with a 32-bit stack segment.  (See the relevant
210  * @ref pxe_x86_pmode16 "implementation note" for more details.)
211  *
212  */
213 PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) {
214         DBG ( "PXENV_UDP_CLOSE" );
215
216         /* Check connection is open */
217         if ( ! pxe_udp.open ) {
218                 pxenv_udp_close->Status = PXENV_STATUS_UDP_CLOSED;
219                 return PXENV_EXIT_SUCCESS; /* Well, it *is* closed */
220         }
221
222         /* Close UDP connection */
223         udp_close_promisc ( &pxe_udp.xfer );
224         pxe_udp.open = 0;
225
226         pxenv_udp_close->Status = PXENV_STATUS_SUCCESS;
227         return PXENV_EXIT_SUCCESS;
228 }
229
230 /**
231  * UDP WRITE
232  *
233  * @v pxenv_udp_write                   Pointer to a struct s_PXENV_UDP_WRITE
234  * @v s_PXENV_UDP_WRITE::ip             Destination IP address
235  * @v s_PXENV_UDP_WRITE::gw             Relay agent IP address, or 0.0.0.0
236  * @v s_PXENV_UDP_WRITE::src_port       Source UDP port, or 0
237  * @v s_PXENV_UDP_WRITE::dst_port       Destination UDP port
238  * @v s_PXENV_UDP_WRITE::buffer_size    Length of the UDP payload
239  * @v s_PXENV_UDP_WRITE::buffer         Address of the UDP payload
240  * @ret #PXENV_EXIT_SUCCESS             Packet was transmitted successfully
241  * @ret #PXENV_EXIT_FAILURE             Packet could not be transmitted
242  * @ret s_PXENV_UDP_WRITE::Status       PXE status code
243  * @err #PXENV_STATUS_UDP_CLOSED        UDP connection is not open
244  * @err #PXENV_STATUS_UNDI_TRANSMIT_ERROR Could not transmit packet
245  *
246  * Transmits a single UDP packet.  A valid IP and UDP header will be
247  * prepended to the payload in s_PXENV_UDP_WRITE::buffer; the buffer
248  * should not contain precomputed IP and UDP headers, nor should it
249  * contain space allocated for these headers.  The first byte of the
250  * buffer will be transmitted as the first byte following the UDP
251  * header.
252  *
253  * If s_PXENV_UDP_WRITE::gw is 0.0.0.0, normal IP routing will take
254  * place.  See the relevant @ref pxe_routing "implementation note" for
255  * more details.
256  *
257  * If s_PXENV_UDP_WRITE::src_port is 0, port 2069 will be used.
258  *
259  * You must have opened a UDP connection with pxenv_udp_open() before
260  * calling pxenv_udp_write().
261  *
262  * On x86, you must set the s_PXE::StatusCallout field to a nonzero
263  * value before calling this function in protected mode.  You cannot
264  * call this function with a 32-bit stack segment.  (See the relevant
265  * @ref pxe_x86_pmode16 "implementation note" for more details.)
266  *
267  * @note Etherboot currently ignores the s_PXENV_UDP_WRITE::gw
268  * parameter.
269  *
270  */
271 PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
272         struct sockaddr_in dest;
273         struct xfer_metadata meta = {
274                 .src = ( struct sockaddr * ) &pxe_udp.local,
275                 .dest = ( struct sockaddr * ) &dest,
276         };
277         size_t len;
278         struct io_buffer *iobuf;
279         userptr_t buffer;
280         int rc;
281
282         DBG ( "PXENV_UDP_WRITE" );
283
284         /* Check connection is open */
285         if ( ! pxe_udp.open ) {
286                 pxenv_udp_write->Status = PXENV_STATUS_UDP_CLOSED;
287                 return PXENV_EXIT_FAILURE;
288         }
289
290         /* Construct destination socket address */
291         memset ( &dest, 0, sizeof ( dest ) );
292         dest.sin_family = AF_INET;
293         dest.sin_addr.s_addr = pxenv_udp_write->ip;
294         dest.sin_port = pxenv_udp_write->dst_port;
295
296         /* Set local (source) port.  PXE spec says source port is 2069
297          * if not specified.  Really, this ought to be set at UDP open
298          * time but hey, we didn't design this API.
299          */
300         pxe_udp.local.sin_port = pxenv_udp_write->src_port;
301         if ( ! pxe_udp.local.sin_port )
302                 pxe_udp.local.sin_port = htons ( 2069 );
303
304         /* FIXME: we ignore the gateway specified, since we're
305          * confident of being able to do our own routing.  We should
306          * probably allow for multiple gateways.
307          */
308
309         /* Allocate and fill data buffer */
310         len = pxenv_udp_write->buffer_size;
311         iobuf = xfer_alloc_iob ( &pxe_udp.xfer, len );
312         if ( ! iobuf ) {
313                 pxenv_udp_write->Status = PXENV_STATUS_OUT_OF_RESOURCES;
314                 return PXENV_EXIT_FAILURE;
315         }
316         buffer = real_to_user ( pxenv_udp_write->buffer.segment,
317                                 pxenv_udp_write->buffer.offset );
318         copy_from_user ( iob_put ( iobuf, len ), buffer, 0, len );
319
320         DBG ( " %04x:%04x+%x %d->%s:%d", pxenv_udp_write->buffer.segment,
321               pxenv_udp_write->buffer.offset, pxenv_udp_write->buffer_size,
322               ntohs ( pxenv_udp_write->src_port ),
323               inet_ntoa ( dest.sin_addr ),
324               ntohs ( pxenv_udp_write->dst_port ) );
325         
326         /* Transmit packet */
327         if ( ( rc = xfer_deliver_iob_meta ( &pxe_udp.xfer, iobuf,
328                                             &meta ) ) != 0 ) {
329                 pxenv_udp_write->Status = PXENV_STATUS ( rc );
330                 return PXENV_EXIT_FAILURE;
331         }
332
333         pxenv_udp_write->Status = PXENV_STATUS_SUCCESS;
334         return PXENV_EXIT_SUCCESS;
335 }
336
337 /**
338  * UDP READ
339  *
340  * @v pxenv_udp_read                    Pointer to a struct s_PXENV_UDP_READ
341  * @v s_PXENV_UDP_READ::dest_ip         Destination IP address, or 0.0.0.0
342  * @v s_PXENV_UDP_READ::d_port          Destination UDP port, or 0
343  * @v s_PXENV_UDP_READ::buffer_size     Size of the UDP payload buffer
344  * @v s_PXENV_UDP_READ::buffer          Address of the UDP payload buffer
345  * @ret #PXENV_EXIT_SUCCESS             A packet has been received
346  * @ret #PXENV_EXIT_FAILURE             No packet has been received
347  * @ret s_PXENV_UDP_READ::Status        PXE status code
348  * @ret s_PXENV_UDP_READ::src_ip        Source IP address
349  * @ret s_PXENV_UDP_READ::dest_ip       Destination IP address
350  * @ret s_PXENV_UDP_READ::s_port        Source UDP port
351  * @ret s_PXENV_UDP_READ::d_port        Destination UDP port
352  * @ret s_PXENV_UDP_READ::buffer_size   Length of UDP payload
353  * @err #PXENV_STATUS_UDP_CLOSED        UDP connection is not open
354  * @err #PXENV_STATUS_FAILURE           No packet was ready to read
355  *
356  * Receive a single UDP packet.  This is a non-blocking call; if no
357  * packet is ready to read, the call will return instantly with
358  * s_PXENV_UDP_READ::Status==PXENV_STATUS_FAILURE.
359  *
360  * If s_PXENV_UDP_READ::dest_ip is 0.0.0.0, UDP packets addressed to
361  * any IP address will be accepted and may be returned to the caller.
362  *
363  * If s_PXENV_UDP_READ::d_port is 0, UDP packets addressed to any UDP
364  * port will be accepted and may be returned to the caller.
365  *
366  * You must have opened a UDP connection with pxenv_udp_open() before
367  * calling pxenv_udp_read().
368  *
369  * On x86, you must set the s_PXE::StatusCallout field to a nonzero
370  * value before calling this function in protected mode.  You cannot
371  * call this function with a 32-bit stack segment.  (See the relevant
372  * @ref pxe_x86_pmode16 "implementation note" for more details.)
373  *
374  * @note The PXE specification (version 2.1) does not state that we
375  * should fill in s_PXENV_UDP_READ::dest_ip and
376  * s_PXENV_UDP_READ::d_port, but Microsoft Windows' NTLDR program
377  * expects us to do so, and will fail if we don't.
378  *
379  */
380 PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) {
381         struct in_addr dest_ip = { .s_addr = pxenv_udp_read->dest_ip };
382         uint16_t d_port = pxenv_udp_read->d_port;
383
384         DBG ( "PXENV_UDP_READ" );
385
386         /* Check connection is open */
387         if ( ! pxe_udp.open ) {
388                 pxenv_udp_read->Status = PXENV_STATUS_UDP_CLOSED;
389                 return PXENV_EXIT_FAILURE;
390         }
391
392         /* Try receiving a packet */
393         pxe_udp.pxenv_udp_read = pxenv_udp_read;
394         step();
395         if ( pxe_udp.pxenv_udp_read ) {
396                 /* No packet received */
397                 pxe_udp.pxenv_udp_read = NULL;
398                 goto no_packet;
399         }
400
401         /* Filter on destination address and/or port */
402         if ( dest_ip.s_addr && ( dest_ip.s_addr != pxenv_udp_read->dest_ip ) )
403                 goto no_packet;
404         if ( d_port && ( d_port != pxenv_udp_read->d_port ) )
405                 goto no_packet;
406
407         DBG ( " %04x:%04x+%x %s:", pxenv_udp_read->buffer.segment,
408               pxenv_udp_read->buffer.offset, pxenv_udp_read->buffer_size,
409               inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->src_ip ) ));
410         DBG ( "%d<-%s:%d",  ntohs ( pxenv_udp_read->s_port ),
411               inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->dest_ip ) ),
412               ntohs ( pxenv_udp_read->d_port ) );
413
414         pxenv_udp_read->Status = PXENV_STATUS_SUCCESS;
415         return PXENV_EXIT_SUCCESS;
416
417  no_packet:
418         pxenv_udp_read->Status = PXENV_STATUS_FAILURE;
419         return PXENV_EXIT_FAILURE;
420 }