These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / core / open.c
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
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., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <stdarg.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <ipxe/xfer.h>
30 #include <ipxe/uri.h>
31 #include <ipxe/socket.h>
32 #include <ipxe/open.h>
33
34 /** @file
35  *
36  * Data transfer interface opening
37  *
38  */
39
40 /**
41  * Find opener for URI scheme
42  *
43  * @v scheme            URI scheme
44  * @ret opener          Opener, or NULL
45  */
46 struct uri_opener * xfer_uri_opener ( const char *scheme ) {
47         struct uri_opener *opener;
48
49         for_each_table_entry ( opener, URI_OPENERS ) {
50                 if ( strcmp ( scheme, opener->scheme ) == 0 )
51                         return opener;
52         }
53         return NULL;
54 }
55
56 /**
57  * Open URI
58  *
59  * @v intf              Data transfer interface
60  * @v uri               URI
61  * @ret rc              Return status code
62  *
63  * The URI will be regarded as being relative to the current working
64  * URI (see churi()).
65  */
66 int xfer_open_uri ( struct interface *intf, struct uri *uri ) {
67         struct uri_opener *opener;
68         struct uri *resolved_uri;
69         int rc;
70
71         /* Resolve URI */
72         resolved_uri = resolve_uri ( cwuri, uri );
73         if ( ! resolved_uri ) {
74                 rc = -ENOMEM;
75                 goto err_resolve_uri;
76         }
77
78         /* Find opener which supports this URI scheme */
79         opener = xfer_uri_opener ( resolved_uri->scheme );
80         if ( ! opener ) {
81                 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to open "
82                        "unsupported URI scheme \"%s\"\n",
83                        INTF_DBG ( intf ), resolved_uri->scheme );
84                 rc = -ENOTSUP;
85                 goto err_opener;
86         }
87
88         /* Call opener */
89         DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " opening %s URI\n",
90                INTF_DBG ( intf ), resolved_uri->scheme );
91         if ( ( rc = opener->open ( intf, resolved_uri ) ) != 0 ) {
92                 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " could not open: "
93                        "%s\n", INTF_DBG ( intf ), strerror ( rc ) );
94                 goto err_open;
95         }
96
97  err_open:
98  err_opener:
99         uri_put ( resolved_uri );
100  err_resolve_uri:
101         return rc;
102 }
103
104 /**
105  * Open URI string
106  *
107  * @v intf              Data transfer interface
108  * @v uri_string        URI string (e.g. "http://ipxe.org/kernel")
109  * @ret rc              Return status code
110  *
111  * The URI will be regarded as being relative to the current working
112  * URI (see churi()).
113  */
114 int xfer_open_uri_string ( struct interface *intf,
115                            const char *uri_string ) {
116         struct uri *uri;
117         int rc;
118
119         DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " opening URI %s\n",
120                INTF_DBG ( intf ), uri_string );
121
122         uri = parse_uri ( uri_string );
123         if ( ! uri )
124                 return -ENOMEM;
125
126         rc = xfer_open_uri ( intf, uri );
127
128         uri_put ( uri );
129         return rc;
130 }
131
132 /**
133  * Open socket
134  *
135  * @v intf              Data transfer interface
136  * @v semantics         Communication semantics (e.g. SOCK_STREAM)
137  * @v peer              Peer socket address
138  * @v local             Local socket address, or NULL
139  * @ret rc              Return status code
140  */
141 int xfer_open_socket ( struct interface *intf, int semantics,
142                        struct sockaddr *peer, struct sockaddr *local ) {
143         struct socket_opener *opener;
144
145         DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " opening (%s,%s) socket\n",
146                INTF_DBG ( intf ), socket_semantics_name ( semantics ),
147                socket_family_name ( peer->sa_family ) );
148
149         for_each_table_entry ( opener, SOCKET_OPENERS ) {
150                 if ( ( opener->semantics == semantics ) &&
151                      ( opener->family == peer->sa_family ) ) {
152                         return opener->open ( intf, peer, local );
153                 }
154         }
155
156         DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to open "
157                "unsupported socket type (%s,%s)\n",
158                INTF_DBG ( intf ), socket_semantics_name ( semantics ),
159                socket_family_name ( peer->sa_family ) );
160         return -ENOTSUP;
161 }
162
163 /**
164  * Open location
165  *
166  * @v intf              Data transfer interface
167  * @v type              Location type
168  * @v args              Remaining arguments depend upon location type
169  * @ret rc              Return status code
170  */
171 int xfer_vopen ( struct interface *intf, int type, va_list args ) {
172         switch ( type ) {
173         case LOCATION_URI_STRING: {
174                 const char *uri_string = va_arg ( args, const char * );
175
176                 return xfer_open_uri_string ( intf, uri_string ); }
177         case LOCATION_URI: {
178                 struct uri *uri = va_arg ( args, struct uri * );
179
180                 return xfer_open_uri ( intf, uri ); }
181         case LOCATION_SOCKET: {
182                 int semantics = va_arg ( args, int );
183                 struct sockaddr *peer = va_arg ( args, struct sockaddr * );
184                 struct sockaddr *local = va_arg ( args, struct sockaddr * );
185
186                 return xfer_open_socket ( intf, semantics, peer, local ); }
187         default:
188                 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to "
189                        "open unsupported location type %d\n",
190                        INTF_DBG ( intf ), type );
191                 return -ENOTSUP;
192         }
193 }
194
195 /**
196  * Open location
197  *
198  * @v intf              Data transfer interface
199  * @v type              Location type
200  * @v ...               Remaining arguments depend upon location type
201  * @ret rc              Return status code
202  */
203 int xfer_open ( struct interface *intf, int type, ... ) {
204         va_list args;
205         int rc;
206
207         va_start ( args, type );
208         rc = xfer_vopen ( intf, type, args );
209         va_end ( args );
210         return rc;
211 }
212
213 /**
214  * Reopen location
215  *
216  * @v intf              Data transfer interface
217  * @v type              Location type
218  * @v args              Remaining arguments depend upon location type
219  * @ret rc              Return status code
220  *
221  * This will close the existing connection and open a new connection
222  * using xfer_vopen().  It is intended to be used as a .vredirect
223  * method handler.
224  */
225 int xfer_vreopen ( struct interface *intf, int type, va_list args ) {
226
227         /* Close existing connection */
228         intf_restart ( intf, 0 );
229
230         /* Open new location */
231         return xfer_vopen ( intf, type, args );
232 }