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