Browse Source

Merge branch 'master' into mcb-tcp-xfer

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
6f0a6c09db

+ 47
- 0
src/core/asprintf.c View File

@@ -0,0 +1,47 @@
1
+#include <stdint.h>
2
+#include <stddef.h>
3
+#include <stdlib.h>
4
+#include <stdio.h>
5
+#include <errno.h>
6
+
7
+/**
8
+ * Write a formatted string to newly allocated memory.
9
+ *
10
+ * @v strp		Pointer to hold allocated string
11
+ * @v fmt		Format string
12
+ * @v args		Arguments corresponding to the format string
13
+ * @ret	len		Length of formatted string
14
+ */
15
+int vasprintf ( char **strp, const char *fmt, va_list args ) {
16
+	size_t len;
17
+	va_list args_tmp;
18
+
19
+	/* Calculate length needed for string */
20
+	va_copy ( args_tmp, args );
21
+	len = ( vsnprintf ( NULL, 0, fmt, args_tmp ) + 1 );
22
+	va_end ( args_tmp );
23
+
24
+	/* Allocate and fill string */
25
+	*strp = malloc ( len );
26
+	if ( ! *strp )
27
+		return -ENOMEM;
28
+	return vsnprintf ( *strp, len, fmt, args );
29
+}
30
+
31
+/**
32
+ * Write a formatted string to newly allocated memory.
33
+ *
34
+ * @v strp		Pointer to hold allocated string
35
+ * @v fmt		Format string
36
+ * @v ...		Arguments corresponding to the format string
37
+ * @ret	len		Length of formatted string
38
+ */
39
+int asprintf ( char **strp, const char *fmt, ... ) {
40
+	va_list args;
41
+	int len;
42
+
43
+	va_start ( args, fmt );
44
+	len = vasprintf ( strp, fmt, args );
45
+	va_end ( args );
46
+	return len;
47
+}

+ 22
- 0
src/core/basename.c View File

@@ -38,3 +38,25 @@ char * basename ( char *path ) {
38 38
 	basename = strrchr ( path, '/' );
39 39
 	return ( basename ? ( basename + 1 ) : path );
40 40
 }
41
+
42
+/**
43
+ * Return directory name from path
44
+ *
45
+ * @v path		Full path
46
+ * @ret dirname		Directory name
47
+ *
48
+ * Note that this function may modify its argument.
49
+ */
50
+char * dirname ( char *path ) {
51
+	char *separator;
52
+
53
+	separator = strrchr ( path, '/' );
54
+	if ( separator == path ) {
55
+		return "/";
56
+	} else if ( separator ) {
57
+		*separator = 0;
58
+		return path;
59
+	} else {
60
+		return ".";
61
+	}
62
+}

+ 2
- 2
src/core/download.c View File

@@ -121,7 +121,7 @@ int start_download ( const char *uri_string, struct async *parent,
121 121
  err:
122 122
 	async_uninit ( &download->async );
123 123
 	ufree ( download->buffer.addr );
124
-	free_uri ( download->uri );
124
+	uri_put ( download->uri );
125 125
 	free ( download );
126 126
 	return rc;
127 127
 }
@@ -150,7 +150,7 @@ static void download_sigchld ( struct async *async,
150 150
 		/* Discard the buffer */
151 151
 		ufree ( download->buffer.addr );
152 152
 	}
153
-	free_uri ( download->uri );
153
+	uri_put ( download->uri );
154 154
 	download->uri = NULL;
155 155
 
156 156
 	/* Terminate ourselves */

+ 1
- 14
src/core/downloader.c View File

@@ -114,19 +114,6 @@ static int downloader_ensure_size ( struct downloader *downloader,
114 114
  *
115 115
  */
116 116
 
117
-/**
118
- * Handle start() event received via job control interface
119
- *
120
- * @v job		Downloader job control interface
121
- */
122
-static void downloader_job_start ( struct job_interface *job ) {
123
-	struct downloader *downloader = 
124
-		container_of ( job, struct downloader, job );
125
-
126
-	/* Start data transfer */
127
-	xfer_request_all ( &downloader->xfer );
128
-}
129
-
130 117
 /**
131 118
  * Handle kill() event received via job control interface
132 119
  *
@@ -142,7 +129,7 @@ static void downloader_job_kill ( struct job_interface *job ) {
142 129
 
143 130
 /** Downloader job control interface operations */
144 131
 static struct job_interface_operations downloader_job_operations = {
145
-	.start		= downloader_job_start,
132
+	.start		= ignore_job_start,
146 133
 	.done		= ignore_job_done,
147 134
 	.kill		= downloader_job_kill,
148 135
 	.progress	= ignore_job_progress,

+ 15
- 12
src/core/hw.c View File

@@ -3,6 +3,7 @@
3 3
 #include <string.h>
4 4
 #include <errno.h>
5 5
 #include <gpxe/refcnt.h>
6
+#include <gpxe/process.h>
6 7
 #include <gpxe/xfer.h>
7 8
 #include <gpxe/open.h>
8 9
 
@@ -15,6 +16,7 @@
15 16
 struct hw {
16 17
 	struct refcnt refcnt;
17 18
 	struct xfer_interface xfer;
19
+	struct process process;
18 20
 };
19 21
 
20 22
 static const char hw_msg[] = "Hello world!\n";
@@ -22,6 +24,7 @@ static const char hw_msg[] = "Hello world!\n";
22 24
 static void hw_finished ( struct hw *hw, int rc ) {
23 25
 	xfer_nullify ( &hw->xfer );
24 26
 	xfer_close ( &hw->xfer, rc );
27
+	process_del ( &hw->process );
25 28
 }
26 29
 
27 30
 static void hw_xfer_close ( struct xfer_interface *xfer, int rc ) {
@@ -30,26 +33,25 @@ static void hw_xfer_close ( struct xfer_interface *xfer, int rc ) {
30 33
 	hw_finished ( hw, rc );
31 34
 }
32 35
 
33
-static int hw_xfer_request ( struct xfer_interface *xfer,
34
-			     off_t start __unused, int whence __unused,
35
-			     size_t len __unused ) {
36
-	struct hw *hw = container_of ( xfer, struct hw, xfer );
37
-	int rc;
38
-
39
-	rc = xfer_deliver_raw ( xfer, hw_msg, sizeof ( hw_msg ) );
40
-	hw_finished ( hw, rc );
41
-	return 0;
42
-}
43
-
44 36
 static struct xfer_interface_operations hw_xfer_operations = {
45 37
 	.close		= hw_xfer_close,
46 38
 	.vredirect	= ignore_xfer_vredirect,
47
-	.request	= hw_xfer_request,
39
+	.request	= ignore_xfer_request,
48 40
 	.seek		= ignore_xfer_seek,
49 41
 	.deliver_iob	= xfer_deliver_as_raw,
50 42
 	.deliver_raw	= ignore_xfer_deliver_raw,
51 43
 };
52 44
 
45
+static void hw_step ( struct process *process ) {
46
+	struct hw *hw = container_of ( process, struct hw, process );
47
+	int rc;
48
+
49
+	if ( xfer_ready ( &hw->xfer ) == 0 ) {
50
+		rc = xfer_deliver_raw ( &hw->xfer, hw_msg, sizeof ( hw_msg ) );
51
+		hw_finished ( hw, rc );
52
+	}
53
+}
54
+
53 55
 static int hw_open ( struct xfer_interface *xfer, struct uri *uri __unused ) {
54 56
 	struct hw *hw;
55 57
 
@@ -59,6 +61,7 @@ static int hw_open ( struct xfer_interface *xfer, struct uri *uri __unused ) {
59 61
 		return -ENOMEM;
60 62
 	memset ( hw, 0, sizeof ( *hw ) );
61 63
 	xfer_init ( &hw->xfer, &hw_xfer_operations, &hw->refcnt );
64
+	process_init ( &hw->process, hw_step, &hw->refcnt );
62 65
 
63 66
 	/* Attach parent interface, mortalise self, and return */
64 67
 	xfer_plug_plug ( &hw->xfer, xfer );

+ 17
- 16
src/core/open.c View File

@@ -52,6 +52,7 @@ static struct socket_opener socket_openers_end[0]
52 52
 int xfer_open_uri ( struct xfer_interface *xfer, const char *uri_string ) {
53 53
 	struct uri *uri;
54 54
 	struct uri_opener *opener;
55
+	int rc = -ENOTSUP;
55 56
 
56 57
 	DBGC ( xfer, "XFER %p opening URI %s\n", xfer, uri_string );
57 58
 
@@ -61,44 +62,45 @@ int xfer_open_uri ( struct xfer_interface *xfer, const char *uri_string ) {
61 62
 
62 63
 	for ( opener = uri_openers ; opener < uri_openers_end ; opener++ ) {
63 64
 		if ( strcmp ( uri->scheme, opener->scheme ) == 0 ) {
64
-			return opener->open ( xfer, uri );
65
+			rc = opener->open ( xfer, uri );
66
+			goto done;
65 67
 		}
66 68
 	}
67 69
 
68 70
 	DBGC ( xfer, "XFER %p attempted to open unsupported URI scheme "
69 71
 	       "\"%s\"\n", xfer, uri->scheme );
70
-	free_uri ( uri );
71
-	return -ENOTSUP;
72
+ done:
73
+	uri_put ( uri );
74
+	return rc;
72 75
 }
73 76
 
74 77
 /**
75 78
  * Open socket
76 79
  *
77 80
  * @v xfer		Data transfer interface
78
- * @v domain		Communication domain (e.g. PF_INET)
79
- * @v type		Communication semantics (e.g. SOCK_STREAM)
81
+ * @v semantics		Communication semantics (e.g. SOCK_STREAM)
80 82
  * @v peer		Peer socket address
81 83
  * @v local		Local socket address, or NULL
82 84
  * @ret rc		Return status code
83 85
  */
84
-int xfer_open_socket ( struct xfer_interface *xfer,
85
-		       int domain, int type, struct sockaddr *peer,
86
-		       struct sockaddr *local ) {
86
+int xfer_open_socket ( struct xfer_interface *xfer, int semantics,
87
+		       struct sockaddr *peer, struct sockaddr *local ) {
87 88
 	struct socket_opener *opener;
88 89
 
89 90
 	DBGC ( xfer, "XFER %p opening (%s,%s) socket\n", xfer,
90
-	       socket_domain_name ( domain ), socket_type_name ( type ) );
91
+	       socket_semantics_name ( semantics ),
92
+	       socket_family_name ( peer->sa_family ) );
91 93
 
92 94
 	for ( opener = socket_openers; opener < socket_openers_end; opener++ ){
93
-		if ( ( opener->domain == domain ) &&
94
-		     ( opener->type == type ) ) {
95
+		if ( ( opener->semantics == semantics ) &&
96
+		     ( opener->family == peer->sa_family ) ) {
95 97
 			return opener->open ( xfer, peer, local );
96 98
 		}
97 99
 	}
98 100
 
99 101
 	DBGC ( xfer, "XFER %p attempted to open unsupported socket type "
100
-	       "(%s,%s)\n", xfer, socket_domain_name ( domain ),
101
-	       socket_type_name ( type ) );
102
+	       "(%s,%s)\n", xfer, socket_semantics_name ( semantics ),
103
+	       socket_family_name ( peer->sa_family ) );
102 104
 	return -ENOTSUP;
103 105
 }
104 106
 
@@ -117,12 +119,11 @@ int xfer_vopen ( struct xfer_interface *xfer, int type, va_list args ) {
117 119
 
118 120
 		return xfer_open_uri ( xfer, uri_string ); }
119 121
 	case LOCATION_SOCKET: {
120
-		int domain = va_arg ( args, int );
121
-		int type = va_arg ( args, int );
122
+		int semantics = va_arg ( args, int );
122 123
 		struct sockaddr *peer = va_arg ( args, struct sockaddr * );
123 124
 		struct sockaddr *local = va_arg ( args, struct sockaddr * );
124 125
 
125
-		return xfer_open_socket ( xfer, domain, type, peer, local ); }
126
+		return xfer_open_socket ( xfer, semantics, peer, local ); }
126 127
 	default:
127 128
 		DBGC ( xfer, "XFER %p attempted to open unsupported location "
128 129
 		       "type %d\n", xfer, type );

+ 8
- 5
src/core/posix_io.c View File

@@ -78,6 +78,7 @@ static void posix_file_free ( struct refcnt *refcnt ) {
78 78
 	struct io_buffer *tmp;
79 79
 
80 80
 	list_for_each_entry_safe ( iobuf, tmp, &file->data, list ) {
81
+		list_del ( &iobuf->list );
81 82
 		free_iob ( iobuf );
82 83
 	}
83 84
 	free ( file );
@@ -190,6 +191,7 @@ static int posix_find_free_fd ( void ) {
190 191
 		if ( ! posix_fd_to_file ( fd ) )
191 192
 			return fd;
192 193
 	}
194
+	DBG ( "POSIX could not find free file descriptor\n" );
193 195
 	return -ENFILE;
194 196
 }
195 197
 
@@ -225,13 +227,11 @@ int open ( const char *uri_string ) {
225 227
 	if ( ( rc = xfer_open_uri ( &file->xfer, uri_string ) ) != 0 )
226 228
 		goto err;
227 229
 
228
-	/* Request data */
229
-	if ( ( rc = xfer_request_all ( &file->xfer ) ) != 0 )
230
-		goto err;
231
-
232 230
 	/* Wait for open to succeed or fail */
233 231
 	while ( list_empty ( &file->data ) ) {
234 232
 		step();
233
+		if ( file->rc == 0 )
234
+			break;
235 235
 		if ( file->rc != -EINPROGRESS ) {
236 236
 			rc = file->rc;
237 237
 			goto err;
@@ -240,6 +240,7 @@ int open ( const char *uri_string ) {
240 240
 
241 241
 	/* Add to list of open files.  List takes reference ownership. */
242 242
 	list_add ( &file->list, &posix_files );
243
+	DBG ( "POSIX opened %s as file %d\n", uri_string, fd );
243 244
 	return fd;
244 245
 
245 246
  err:
@@ -279,8 +280,10 @@ ssize_t read_user ( int fd, userptr_t buffer, off_t offset, size_t max_len ) {
279 280
 			copy_to_user ( buffer, offset, iobuf->data,
280 281
 				       frag_len );
281 282
 			iob_pull ( iobuf, frag_len );
282
-			if ( ! iob_len ( iobuf ) )
283
+			if ( ! iob_len ( iobuf ) ) {
284
+				list_del ( &iobuf-> list );
283 285
 				free_iob ( iobuf );
286
+			}
284 287
 			file->pos += frag_len;
285 288
 			len += frag_len;
286 289
 			offset += frag_len;

+ 22
- 4
src/core/process.c View File

@@ -31,25 +31,43 @@
31 31
 static LIST_HEAD ( run_queue );
32 32
 
33 33
 /**
34
- * Add process to run queue
34
+ * Add process to process list
35 35
  *
36 36
  * @v process		Process
37 37
  */
38
-void schedule ( struct process *process ) {
38
+void process_add ( struct process *process ) {
39
+	ref_get ( process->refcnt );
39 40
 	list_add_tail ( &process->list, &run_queue );
40 41
 }
41 42
 
43
+/**
44
+ * Remove process from process list
45
+ *
46
+ * @v process		Process
47
+ *
48
+ * It is safe to call process_del() multiple times; further calls will
49
+ * have no effect.
50
+ */
51
+void process_del ( struct process *process ) {
52
+	if ( ! list_empty ( &process->list ) ) {
53
+		list_del ( &process->list );
54
+		INIT_LIST_HEAD ( &process->list );
55
+		ref_put ( process->refcnt );
56
+	}
57
+}
58
+
42 59
 /**
43 60
  * Single-step a single process
44 61
  *
45
- * This removes the first process from the run queue and executes a
46
- * single step of that process.
62
+ * This executes a single step of the first process in the run queue,
63
+ * and moves the process to the end of the run queue.
47 64
  */
48 65
 void step ( void ) {
49 66
 	struct process *process;
50 67
 
51 68
 	list_for_each_entry ( process, &run_queue, list ) {
52 69
 		list_del ( &process->list );
70
+		list_add_tail ( &process->list, &run_queue );
53 71
 		process->step ( process );
54 72
 		break;
55 73
 	}

+ 4
- 4
src/core/refcnt.c View File

@@ -39,8 +39,8 @@ void ref_get ( struct refcnt *refcnt ) {
39 39
 
40 40
 	refcnt->refcnt++;
41 41
 
42
-	DBGC ( refcnt, "REFCNT %p incremented to %d\n",
43
-	       refcnt, refcnt->refcnt );
42
+	DBGC2 ( refcnt, "REFCNT %p incremented to %d\n",
43
+		refcnt, refcnt->refcnt );
44 44
 }
45 45
 
46 46
 /**
@@ -59,8 +59,8 @@ void ref_put ( struct refcnt *refcnt ) {
59 59
 		return;
60 60
 
61 61
 	refcnt->refcnt--;
62
-	DBGC ( refcnt, "REFCNT %p decremented to %d\n",
63
-	       refcnt, refcnt->refcnt );
62
+	DBGC2 ( refcnt, "REFCNT %p decremented to %d\n",
63
+		refcnt, refcnt->refcnt );
64 64
 
65 65
 	if ( refcnt->refcnt >= 0 )
66 66
 		return;

+ 221
- 20
src/core/uri.c View File

@@ -25,8 +25,36 @@
25 25
 #include <stdint.h>
26 26
 #include <stdlib.h>
27 27
 #include <string.h>
28
+#include <libgen.h>
29
+#include <gpxe/vsprintf.h>
28 30
 #include <gpxe/uri.h>
29 31
 
32
+/**
33
+ * Dump URI for debugging
34
+ *
35
+ * @v uri		URI
36
+ */
37
+static void dump_uri ( struct uri *uri ) {
38
+	if ( uri->scheme )
39
+		DBG ( " scheme \"%s\"", uri->scheme );
40
+	if ( uri->opaque )
41
+		DBG ( " opaque \"%s\"", uri->opaque );
42
+	if ( uri->user )
43
+		DBG ( " user \"%s\"", uri->user );
44
+	if ( uri->password )
45
+		DBG ( " password \"%s\"", uri->password );
46
+	if ( uri->host )
47
+		DBG ( " host \"%s\"", uri->host );
48
+	if ( uri->port )
49
+		DBG ( " port \"%s\"", uri->port );
50
+	if ( uri->path )
51
+		DBG ( " path \"%s\"", uri->path );
52
+	if ( uri->query )
53
+		DBG ( " query \"%s\"", uri->query );
54
+	if ( uri->fragment )
55
+		DBG ( " fragment \"%s\"", uri->fragment );
56
+}
57
+
30 58
 /**
31 59
  * Parse URI
32 60
  *
@@ -35,7 +63,7 @@
35 63
  *
36 64
  * Splits a URI into its component parts.  The return URI structure is
37 65
  * dynamically allocated and must eventually be freed by calling
38
- * free_uri().
66
+ * uri_put().
39 67
  */
40 68
 struct uri * parse_uri ( const char *uri_string ) {
41 69
 	struct uri *uri;
@@ -136,25 +164,8 @@ struct uri * parse_uri ( const char *uri_string ) {
136 164
 	}
137 165
 
138 166
  done:
139
-	DBG ( "URI \"%s\" split into", raw );
140
-	if ( uri->scheme )
141
-		DBG ( " scheme \"%s\"", uri->scheme );
142
-	if ( uri->opaque )
143
-		DBG ( " opaque \"%s\"", uri->opaque );
144
-	if ( uri->user )
145
-		DBG ( " user \"%s\"", uri->user );
146
-	if ( uri->password )
147
-		DBG ( " password \"%s\"", uri->password );
148
-	if ( uri->host )
149
-		DBG ( " host \"%s\"", uri->host );
150
-	if ( uri->port )
151
-		DBG ( " port \"%s\"", uri->port );
152
-	if ( uri->path )
153
-		DBG ( " path \"%s\"", uri->path );
154
-	if ( uri->query )
155
-		DBG ( " query \"%s\"", uri->query );
156
-	if ( uri->fragment )
157
-		DBG ( " fragment \"%s\"", uri->fragment );
167
+	DBG ( "URI \"%s\" split into", uri_string );
168
+	dump_uri ( uri );
158 169
 	DBG ( "\n" );
159 170
 
160 171
 	return uri;
@@ -170,3 +181,193 @@ struct uri * parse_uri ( const char *uri_string ) {
170 181
 unsigned int uri_port ( struct uri *uri, unsigned int default_port ) {
171 182
 	return ( uri->port ? strtoul ( uri->port, NULL, 0 ) : default_port );
172 183
 }
184
+
185
+/**
186
+ * Unparse URI
187
+ *
188
+ * @v buf		Buffer to fill with URI string
189
+ * @v size		Size of buffer
190
+ * @v uri		URI to write into buffer
191
+ * @ret len		Length of URI string
192
+ */
193
+int unparse_uri ( char *buf, size_t size, struct uri *uri ) {
194
+	int used = 0;
195
+
196
+	DBG ( "URI unparsing" );
197
+	dump_uri ( uri );
198
+	DBG ( "\n" );
199
+
200
+	/* Special-case opaque URIs */
201
+	if ( uri->opaque ) {
202
+		return ssnprintf ( ( buf + used ), ( size - used ),
203
+				   "%s:%s", uri->scheme, uri->opaque );
204
+	}
205
+
206
+	/* scheme:// */
207
+	if ( uri->scheme ) {
208
+		used += ssnprintf ( ( buf + used ), ( size - used ),
209
+				    "%s://", uri->scheme );
210
+	}
211
+
212
+	/* [user[:password]@]host[:port] */
213
+	if ( uri->host ) {
214
+		if ( uri->user ) {
215
+			used += ssnprintf ( ( buf + used ), ( size - used ),
216
+					    "%s", uri->user );
217
+			if ( uri->password ) {
218
+				used += ssnprintf ( ( buf + used ),
219
+						    ( size - used ),
220
+						    ":%s", uri->password );
221
+			}
222
+			used += ssnprintf ( ( buf + used ), ( size - used ),
223
+					    "@" );
224
+		}
225
+		used += ssnprintf ( ( buf + used ), ( size - used ), "%s",
226
+				    uri->host );
227
+		if ( uri->port ) {
228
+			used += ssnprintf ( ( buf + used ), ( size - used ),
229
+					    ":%s", uri->port );
230
+		}
231
+	}
232
+
233
+	/* /path */
234
+	if ( uri->path ) {
235
+		used += ssnprintf ( ( buf + used ), ( size - used ),
236
+				    "%s", uri->path );
237
+	}
238
+
239
+	/* ?query */
240
+	if ( uri->query ) {
241
+		used += ssnprintf ( ( buf + used ), ( size - used ),
242
+				    "?%s", uri->query );
243
+	}
244
+
245
+	/* #fragment */
246
+	if ( uri->fragment ) {
247
+		used += ssnprintf ( ( buf + used ), ( size - used ),
248
+				    "#%s", uri->fragment );
249
+	}
250
+
251
+	return used;
252
+}
253
+
254
+/**
255
+ * Duplicate URI
256
+ *
257
+ * @v uri		URI
258
+ * @ret uri		Duplicate URI
259
+ *
260
+ * Creates a modifiable copy of a URI.
261
+ */
262
+struct uri * uri_dup ( struct uri *uri ) {
263
+	size_t len = ( unparse_uri ( NULL, 0, uri ) + 1 );
264
+	char buf[len];
265
+
266
+	unparse_uri ( buf, len, uri );
267
+	return parse_uri ( buf );
268
+}
269
+
270
+/**
271
+ * Resolve base+relative path
272
+ *
273
+ * @v base_uri		Base path
274
+ * @v relative_uri	Relative path
275
+ * @ret resolved_uri	Resolved path
276
+ *
277
+ * Takes a base path (e.g. "/var/lib/tftpboot/vmlinuz" and a relative
278
+ * path (e.g. "initrd.gz") and produces a new path
279
+ * (e.g. "/var/lib/tftpboot/initrd.gz").  Note that any non-directory
280
+ * portion of the base path will automatically be stripped; this
281
+ * matches the semantics used when resolving the path component of
282
+ * URIs.
283
+ */
284
+char * resolve_path ( const char *base_path,
285
+		      const char *relative_path ) {
286
+	size_t base_len = ( strlen ( base_path ) + 1 );
287
+	char base_path_copy[base_len];
288
+	char *base_tmp = base_path_copy;
289
+	char *resolved;
290
+
291
+	/* If relative path is absolute, just re-use it */
292
+	if ( relative_path[0] == '/' )
293
+		return strdup ( relative_path );
294
+
295
+	/* Create modifiable copy of path for dirname() */
296
+	memcpy ( base_tmp, base_path, base_len );
297
+	base_tmp = dirname ( base_tmp );
298
+
299
+	/* Process "./" and "../" elements */
300
+	while ( *relative_path == '.' ) {
301
+		relative_path++;
302
+		if ( *relative_path == 0 ) {
303
+			/* Do nothing */
304
+		} else if ( *relative_path == '/' ) {
305
+			relative_path++;
306
+		} else if ( *relative_path == '.' ) {
307
+			relative_path++;
308
+			if ( *relative_path == 0 ) {
309
+				base_tmp = dirname ( base_tmp );
310
+			} else if ( *relative_path == '/' ) {
311
+				base_tmp = dirname ( base_tmp );
312
+				relative_path++;
313
+			} else {
314
+				relative_path -= 2;
315
+				break;
316
+			}
317
+		} else {
318
+			relative_path--;
319
+			break;
320
+		}
321
+	}
322
+
323
+	/* Create and return new path */
324
+	if ( asprintf ( &resolved, "%s%s%s", base_tmp,
325
+			( ( base_tmp[ strlen ( base_tmp ) - 1 ] == '/' ) ?
326
+			  "" : "/" ), relative_path ) < 0 )
327
+		return NULL;
328
+
329
+	return resolved;
330
+}
331
+
332
+/**
333
+ * Resolve base+relative URI
334
+ *
335
+ * @v base_uri		Base URI
336
+ * @v relative_uri	Relative URI
337
+ * @ret resolved_uri	Resolved URI
338
+ *
339
+ * Takes a base URI (e.g. "http://etherboot.org/kernels/vmlinuz" and a
340
+ * relative URI (e.g. "../initrds/initrd.gz") and produces a new URI
341
+ * (e.g. "http://etherboot.org/initrds/initrd.gz").
342
+ */
343
+struct uri * resolve_uri ( struct uri *base_uri,
344
+			   struct uri *relative_uri ) {
345
+	struct uri tmp_uri;
346
+	char *tmp_path = NULL;
347
+	struct uri *new_uri;
348
+
349
+	/* If relative URI is absolute, just re-use it */
350
+	if ( uri_is_absolute ( relative_uri ) )
351
+		return uri_get ( relative_uri );
352
+
353
+	/* Mangle URI */
354
+	memcpy ( &tmp_uri, base_uri, sizeof ( tmp_uri ) );
355
+	if ( relative_uri->path ) {
356
+		tmp_path = resolve_path ( ( base_uri->path ?
357
+					    base_uri->path : "/" ),
358
+					  relative_uri->path );
359
+		tmp_uri.path = tmp_path;
360
+		tmp_uri.query = relative_uri->query;
361
+		tmp_uri.fragment = relative_uri->fragment;
362
+	} else if ( relative_uri->query ) {
363
+		tmp_uri.query = relative_uri->query;
364
+		tmp_uri.fragment = relative_uri->fragment;
365
+	} else if ( relative_uri->fragment ) {
366
+		tmp_uri.fragment = relative_uri->fragment;
367
+	}
368
+
369
+	/* Create demangled URI */
370
+	new_uri = uri_dup ( &tmp_uri );
371
+	free ( tmp_path );
372
+	return new_uri;
373
+}

+ 39
- 0
src/core/vsprintf.c View File

@@ -338,6 +338,45 @@ int snprintf ( char *buf, size_t size, const char *fmt, ... ) {
338 338
 	return i;
339 339
 }
340 340
 
341
+/**
342
+ * Version of vsnprintf() that accepts a signed buffer size
343
+ *
344
+ * @v buf		Buffer into which to write the string
345
+ * @v size		Size of buffer
346
+ * @v fmt		Format string
347
+ * @v args		Arguments corresponding to the format string
348
+ * @ret len		Length of formatted string
349
+ */
350
+int vssnprintf ( char *buf, ssize_t ssize, const char *fmt, va_list args ) {
351
+
352
+	/* Treat negative buffer size as zero buffer size */
353
+	if ( ssize < 0 )
354
+		ssize = 0;
355
+
356
+	/* Hand off to vsnprintf */
357
+	return vsnprintf ( buf, ssize, fmt, args );
358
+}
359
+
360
+/**
361
+ * Version of vsnprintf() that accepts a signed buffer size
362
+ *
363
+ * @v buf		Buffer into which to write the string
364
+ * @v size		Size of buffer
365
+ * @v fmt		Format string
366
+ * @v ...		Arguments corresponding to the format string
367
+ * @ret len		Length of formatted string
368
+ */
369
+int ssnprintf ( char *buf, ssize_t ssize, const char *fmt, ... ) {
370
+	va_list args;
371
+	int len;
372
+
373
+	/* Hand off to vssnprintf */
374
+	va_start ( args, fmt );
375
+	len = vssnprintf ( buf, ssize, fmt, args );
376
+	va_end ( args );
377
+	return len;
378
+}
379
+
341 380
 /**
342 381
  * Write character to console
343 382
  *

+ 103
- 10
src/core/xfer.c View File

@@ -17,6 +17,7 @@
17 17
  */
18 18
 
19 19
 #include <string.h>
20
+#include <stdio.h>
20 21
 #include <errno.h>
21 22
 #include <gpxe/xfer.h>
22 23
 
@@ -35,6 +36,8 @@
35 36
 void xfer_close ( struct xfer_interface *xfer, int rc ) {
36 37
 	struct xfer_interface *dest = xfer_get_dest ( xfer );
37 38
 
39
+	DBGC ( xfer, "XFER %p->%p close\n", xfer, dest );
40
+
38 41
 	dest->op->close ( dest, rc );
39 42
 	xfer_unplug ( xfer );
40 43
 	xfer_put ( dest );
@@ -52,7 +55,14 @@ int xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ) {
52 55
 	struct xfer_interface *dest = xfer_get_dest ( xfer );
53 56
 	int rc;
54 57
 
58
+	DBGC ( xfer, "XFER %p->%p redirect\n", xfer, dest );
59
+
55 60
 	rc = dest->op->vredirect ( dest, type, args );
61
+
62
+	if ( rc != 0 ) {
63
+		DBGC ( xfer, "XFER %p<-%p redirect: %s\n", xfer, dest,
64
+		       strerror ( rc ) );
65
+	}
56 66
 	xfer_put ( dest );
57 67
 	return rc;
58 68
 }
@@ -89,21 +99,19 @@ int xfer_request ( struct xfer_interface *xfer, off_t offset, int whence,
89 99
 	struct xfer_interface *dest = xfer_get_dest ( xfer );
90 100
 	int rc;
91 101
 
102
+	DBGC ( xfer, "XFER %p->%p request %s+%ld %zd\n", xfer, dest,
103
+	       whence_text ( whence ), offset, len );
104
+
92 105
 	rc = dest->op->request ( dest, offset, whence, len );
106
+
107
+	if ( rc != 0 ) {
108
+		DBGC ( xfer, "XFER %p<-%p request: %s\n", xfer, dest,
109
+		       strerror ( rc ) );
110
+	}
93 111
 	xfer_put ( dest );
94 112
 	return rc;
95 113
 }
96 114
 
97
-/**
98
- * Request all data
99
- *
100
- * @v xfer		Data transfer interface
101
- * @ret rc		Return status code
102
- */
103
-int xfer_request_all ( struct xfer_interface *xfer ) {
104
-	return xfer_request ( xfer, 0, SEEK_SET, ~( ( size_t ) 0 ) );
105
-}
106
-
107 115
 /**
108 116
  * Seek to position
109 117
  *
@@ -116,11 +124,33 @@ int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
116 124
 	struct xfer_interface *dest = xfer_get_dest ( xfer );
117 125
 	int rc;
118 126
 
127
+	DBGC ( xfer, "XFER %p->%p seek %s+%ld\n", xfer, dest,
128
+	       whence_text ( whence ), offset );
129
+
119 130
 	rc = dest->op->seek ( dest, offset, whence );
131
+
132
+	if ( rc != 0 ) {
133
+		DBGC ( xfer, "XFER %p<-%p seek: %s\n", xfer, dest,
134
+		       strerror ( rc ) );
135
+	}
120 136
 	xfer_put ( dest );
121 137
 	return rc;
122 138
 }
123 139
 
140
+/**
141
+ * Test to see if interface is ready to accept data
142
+ *
143
+ * @v xfer		Data transfer interface
144
+ * @ret rc		Return status code
145
+ *
146
+ * This test is optional; the data transfer interface may wish that it
147
+ * does not yet wish to accept data, but cannot prevent attempts to
148
+ * deliver data to it.
149
+ */
150
+int xfer_ready ( struct xfer_interface *xfer ) {
151
+	return xfer_seek ( xfer, 0, SEEK_CUR );
152
+}
153
+
124 154
 /**
125 155
  * Allocate I/O buffer
126 156
  *
@@ -132,7 +162,13 @@ struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
132 162
 	struct xfer_interface *dest = xfer_get_dest ( xfer );
133 163
 	struct io_buffer *iobuf;
134 164
 
165
+	DBGC ( xfer, "XFER %p->%p alloc_iob %zd\n", xfer, dest, len );
166
+
135 167
 	iobuf = dest->op->alloc_iob ( dest, len );
168
+
169
+	if ( ! iobuf ) {
170
+		DBGC ( xfer, "XFER %p<-%p alloc_iob failed\n", xfer, dest );
171
+	}
136 172
 	xfer_put ( dest );
137 173
 	return iobuf;
138 174
 }
@@ -148,7 +184,15 @@ int xfer_deliver_iob ( struct xfer_interface *xfer, struct io_buffer *iobuf ) {
148 184
 	struct xfer_interface *dest = xfer_get_dest ( xfer );
149 185
 	int rc;
150 186
 
187
+	DBGC ( xfer, "XFER %p->%p deliver_iob %zd\n", xfer, dest,
188
+	       iob_len ( iobuf ) );
189
+
151 190
 	rc = dest->op->deliver_iob ( dest, iobuf );
191
+
192
+	if ( rc != 0 ) {
193
+		DBGC ( xfer, "XFER %p<-%p deliver_iob: %s\n", xfer, dest,
194
+		       strerror ( rc ) );
195
+	}
152 196
 	xfer_put ( dest );
153 197
 	return rc;
154 198
 }
@@ -165,11 +209,60 @@ int xfer_deliver_raw ( struct xfer_interface *xfer,
165 209
 	struct xfer_interface *dest = xfer_get_dest ( xfer );
166 210
 	int rc;
167 211
 
212
+	DBGC ( xfer, "XFER %p->%p deliver_raw %p+%zd\n", xfer, dest,
213
+	       data, len );
214
+
168 215
 	rc = dest->op->deliver_raw ( dest, data, len );
216
+
217
+	if ( rc != 0 ) {
218
+		DBGC ( xfer, "XFER %p<-%p deliver_raw: %s\n", xfer, dest,
219
+		       strerror ( rc ) );
220
+	}
169 221
 	xfer_put ( dest );
170 222
 	return rc;
171 223
 }
172 224
 
225
+/**
226
+ * Deliver formatted string
227
+ *
228
+ * @v xfer		Data transfer interface
229
+ * @v format		Format string
230
+ * @v args		Arguments corresponding to the format string
231
+ * @ret rc		Return status code
232
+ */
233
+int xfer_vprintf ( struct xfer_interface *xfer, const char *format,
234
+		   va_list args ) {
235
+	size_t len;
236
+	va_list args_tmp;
237
+
238
+	va_copy ( args_tmp, args );
239
+	len = vsnprintf ( NULL, 0, format, args );
240
+	{
241
+		char buf[len + 1];
242
+		vsnprintf ( buf, sizeof ( buf ), format, args_tmp );
243
+		va_end ( args_tmp );
244
+		return xfer_deliver_raw ( xfer, buf, len );
245
+	}
246
+}
247
+
248
+/**
249
+ * Deliver formatted string
250
+ *
251
+ * @v xfer		Data transfer interface
252
+ * @v format		Format string
253
+ * @v ...		Arguments corresponding to the format string
254
+ * @ret rc		Return status code
255
+ */
256
+int xfer_printf ( struct xfer_interface *xfer, const char *format, ... ) {
257
+	va_list args;
258
+	int rc;
259
+
260
+	va_start ( args, format );
261
+	rc = xfer_vprintf ( xfer, format, args );
262
+	va_end ( args );
263
+	return rc;
264
+}
265
+
173 266
 /****************************************************************************
174 267
  *
175 268
  * Helper methods

+ 0
- 867
src/crypto/axtls/asn1.c View File

@@ -1,867 +0,0 @@
1
-/*
2
- *  Copyright(C) 2006 Cameron Rich
3
- *
4
- *  This library is free software; you can redistribute it and/or modify
5
- *  it under the terms of the GNU Lesser General Public License as published by
6
- *  the Free Software Foundation; either version 2.1 of the License, or
7
- *  (at your option) any later version.
8
- *
9
- *  This library is distributed in the hope that it will be useful,
10
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
- *  GNU Lesser General Public License for more details.
13
- *
14
- *  You should have received a copy of the GNU Lesser General Public License
15
- *  along with this library; if not, write to the Free Software
16
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
- */
18
-
19
-/**
20
- * @file asn1.c
21
- * 
22
- * Some primitive asn methods for extraction rsa modulus information. It also
23
- * is used for retrieving information from X.509 certificates.
24
- */
25
-
26
-#include <stdio.h>
27
-#include <stdlib.h>
28
-#include <string.h>
29
-#include <time.h>
30
-#include "crypto.h"
31
-
32
-#define SIG_OID_PREFIX_SIZE     8
33
-
34
-#define SIG_TYPE_MD2            0x02
35
-#define SIG_TYPE_MD5            0x04
36
-#define SIG_TYPE_SHA1           0x05
37
-
38
-/* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
39
-static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] = 
40
-{
41
-    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01
42
-};
43
-
44
-/* CN, O, OU */
45
-static const uint8_t g_dn_types[] = { 3, 10, 11 };
46
-
47
-static int get_asn1_length(const uint8_t *buf, int *offset)
48
-{
49
-    int len, i;
50
-
51
-    if (!(buf[*offset] & 0x80)) /* short form */
52
-    {
53
-        len = buf[(*offset)++];
54
-    }
55
-    else    /* long form */
56
-    {
57
-        int length_bytes = buf[(*offset)++]&0x7f;
58
-        len = 0;
59
-        for (i = 0; i < length_bytes; i++)
60
-        {
61
-            len <<= 8;
62
-            len += buf[(*offset)++];
63
-        }
64
-    }
65
-
66
-    return len;
67
-}
68
-
69
-/**
70
- * Skip the ASN1.1 object type and its length. Get ready to read the object's
71
- * data.
72
- */
73
-int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type)
74
-{
75
-    if (buf[*offset] != obj_type)
76
-        return X509_NOT_OK;
77
-    (*offset)++;
78
-    return get_asn1_length(buf, offset);
79
-}
80
-
81
-/**
82
- * Skip over an ASN.1 object type completely. Get ready to read the next
83
- * object.
84
- */
85
-int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
86
-{
87
-    int len;
88
-
89
-    if (buf[*offset] != obj_type)
90
-        return X509_NOT_OK;
91
-    (*offset)++;
92
-    len = get_asn1_length(buf, offset);
93
-    *offset += len;
94
-    return 0;
95
-}
96
-
97
-/**
98
- * Read an integer value for ASN.1 data
99
- * Note: This function allocates memory which must be freed by the user.
100
- */
101
-int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object)
102
-{
103
-    int len;
104
-
105
-    if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
106
-        goto end_int_array;
107
-
108
-    *object = (uint8_t *)malloc(len);
109
-    memcpy(*object, &buf[*offset], len);
110
-    *offset += len;
111
-
112
-end_int_array:
113
-    return len;
114
-}
115
-
116
-#if 0
117
-
118
-/**
119
- * Get all the RSA private key specifics from an ASN.1 encoded file 
120
- */
121
-int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx)
122
-{
123
-    int offset = 7;
124
-    uint8_t *modulus, *priv_exp, *pub_exp;
125
-    int mod_len, priv_len, pub_len;
126
-#ifdef CONFIG_BIGINT_CRT
127
-    uint8_t *p, *q, *dP, *dQ, *qInv;
128
-    int p_len, q_len, dP_len, dQ_len, qInv_len;
129
-#endif
130
-
131
-    /* not in der format */
132
-    if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */
133
-    {
134
-#ifdef CONFIG_SSL_FULL_MODE
135
-        printf("Error: This is not a valid ASN.1 file\n");
136
-#endif
137
-        return X509_INVALID_PRIV_KEY;
138
-    }
139
-
140
-    /* initialise the RNG */
141
-    RNG_initialize(buf, len);
142
-
143
-    mod_len = asn1_get_int(buf, &offset, &modulus);
144
-    pub_len = asn1_get_int(buf, &offset, &pub_exp);
145
-    priv_len = asn1_get_int(buf, &offset, &priv_exp);
146
-
147
-    if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
148
-        return X509_INVALID_PRIV_KEY;
149
-
150
-#ifdef CONFIG_BIGINT_CRT
151
-    p_len = asn1_get_int(buf, &offset, &p);
152
-    q_len = asn1_get_int(buf, &offset, &q);
153
-    dP_len = asn1_get_int(buf, &offset, &dP);
154
-    dQ_len = asn1_get_int(buf, &offset, &dQ);
155
-    qInv_len = asn1_get_int(buf, &offset, &qInv);
156
-
157
-    if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
158
-        return X509_INVALID_PRIV_KEY;
159
-
160
-    RSA_priv_key_new(rsa_ctx, 
161
-            modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len,
162
-            p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len);
163
-
164
-    free(p);
165
-    free(q);
166
-    free(dP);
167
-    free(dQ);
168
-    free(qInv);
169
-#else
170
-    RSA_priv_key_new(rsa_ctx, 
171
-            modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len);
172
-#endif
173
-
174
-    free(modulus);
175
-    free(priv_exp);
176
-    free(pub_exp);
177
-    return X509_OK;
178
-}
179
-
180
-/**
181
- * Get the time of a certificate. Ignore hours/minutes/seconds.
182
- */
183
-static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
184
-{
185
-    int ret = X509_NOT_OK, len, t_offset;
186
-    struct tm tm;
187
-
188
-    if (buf[(*offset)++] != ASN1_UTC_TIME)
189
-        goto end_utc_time;
190
-    len = get_asn1_length(buf, offset);
191
-    t_offset = *offset;
192
-
193
-    memset(&tm, 0, sizeof(struct tm));
194
-    tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
195
-
196
-    if (tm.tm_year <= 50)    /* 1951-2050 thing */
197
-    {
198
-        tm.tm_year += 100;
199
-    }
200
-
201
-    tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
202
-    tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
203
-    *t = mktime(&tm);
204
-    *offset += len;
205
-    ret = X509_OK;
206
-
207
-end_utc_time:
208
-    return ret;
209
-}
210
-
211
-/**
212
- * Get the version type of a certificate (which we don't actually care about)
213
- */
214
-static int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
215
-{
216
-    int ret = X509_NOT_OK;
217
-
218
-    (*offset) += 2;        /* get past explicit tag */
219
-    if (asn1_skip_obj(cert, offset, ASN1_INTEGER))
220
-        goto end_version;
221
-
222
-    ret = X509_OK;
223
-end_version:
224
-    return ret;
225
-}
226
-
227
-/**
228
- * Retrieve the notbefore and notafter certificate times.
229
- */
230
-static int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
231
-{
232
-    return (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
233
-              asn1_get_utc_time(cert, offset, &x509_ctx->not_before) ||
234
-              asn1_get_utc_time(cert, offset, &x509_ctx->not_after));
235
-}
236
-
237
-/**
238
- * Get the components of a distinguished name 
239
- */
240
-static int asn1_get_oid_x520(const uint8_t *buf, int *offset)
241
-{
242
-    int dn_type = 0;
243
-    int len;
244
-
245
-    if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
246
-        goto end_oid;
247
-
248
-    /* expect a sequence of 2.5.4.[x] where x is a one of distinguished name 
249
-       components we are interested in. */
250
-    if (len == 3 && buf[(*offset)++] == 0x55 && buf[(*offset)++] == 0x04)
251
-        dn_type = buf[(*offset)++];
252
-    else
253
-    {
254
-        *offset += len;     /* skip over it */
255
-    }
256
-
257
-end_oid:
258
-    return dn_type;
259
-}
260
-
261
-/**
262
- * Obtain an ASN.1 printable string type.
263
- */
264
-static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
265
-{
266
-    int len = X509_NOT_OK;
267
-
268
-    /* some certs have this awful crud in them for some reason */
269
-    if (buf[*offset] != ASN1_PRINTABLE_STR && 
270
-            buf[*offset] != ASN1_TELETEX_STR && buf[*offset] != ASN1_IA5_STR)
271
-        goto end_pnt_str;
272
-
273
-    (*offset)++;
274
-    len = get_asn1_length(buf, offset);
275
-    *str = (char *)malloc(len+1);       /* allow for null */
276
-    memcpy(*str, &buf[*offset], len);
277
-    (*str)[len] = 0;                    /* null terminate */
278
-    *offset += len;
279
-end_pnt_str:
280
-    return len;
281
-}
282
-
283
-/**
284
- * Get the subject name (or the issuer) of a certificate.
285
- */
286
-static int asn1_name(const uint8_t *cert, int *offset, char *dn[])
287
-{
288
-    int ret = X509_NOT_OK;
289
-    int dn_type;
290
-    char *tmp = NULL;
291
-
292
-    if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
293
-        goto end_name;
294
-
295
-    while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
296
-    {
297
-        int i, found = 0;
298
-
299
-        if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
300
-               (dn_type = asn1_get_oid_x520(cert, offset)) < 0)
301
-            goto end_name;
302
-
303
-        if (asn1_get_printable_str(cert, offset, &tmp) < 0)
304
-        {
305
-            free(tmp);
306
-            goto end_name;
307
-        }
308
-
309
-        /* find the distinguished named type */
310
-        for (i = 0; i < X509_NUM_DN_TYPES; i++)
311
-        {
312
-            if (dn_type == g_dn_types[i])
313
-            {
314
-                if (dn[i] == NULL)
315
-                {
316
-                    dn[i] = tmp;
317
-                    found = 1;
318
-                    break;
319
-                }
320
-            }
321
-        }
322
-
323
-        if (found == 0) /* not found so get rid of it */
324
-        {
325
-            free(tmp);
326
-        }
327
-    }
328
-
329
-    ret = X509_OK;
330
-end_name:
331
-    return ret;
332
-}
333
-
334
-/**
335
- * Read the modulus and public exponent of a certificate.
336
- */
337
-static int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
338
-{
339
-    int ret = X509_NOT_OK, mod_len, pub_len;
340
-    uint8_t *modulus, *pub_exp;
341
-
342
-    if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
343
-            asn1_skip_obj(cert, offset, ASN1_SEQUENCE) ||
344
-            asn1_next_obj(cert, offset, ASN1_BIT_STRING) < 0)
345
-        goto end_pub_key;
346
-
347
-    (*offset)++;
348
-
349
-    if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
350
-        goto end_pub_key;
351
-
352
-    mod_len = asn1_get_int(cert, offset, &modulus);
353
-    pub_len = asn1_get_int(cert, offset, &pub_exp);
354
-
355
-    RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
356
-
357
-    free(modulus);
358
-    free(pub_exp);
359
-    ret = X509_OK;
360
-
361
-end_pub_key:
362
-    return ret;
363
-}
364
-
365
-#ifdef CONFIG_SSL_CERT_VERIFICATION
366
-/**
367
- * Read the signature of the certificate.
368
- */
369
-static int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
370
-{
371
-    int ret = X509_NOT_OK;
372
-
373
-    if (cert[(*offset)++] != ASN1_BIT_STRING)
374
-        goto end_sig;
375
-
376
-    x509_ctx->sig_len = get_asn1_length(cert, offset);
377
-    x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
378
-    memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
379
-    *offset += x509_ctx->sig_len;
380
-    ret = X509_OK;
381
-
382
-end_sig:
383
-    return ret;
384
-}
385
-
386
-/*
387
- * Compare 2 distinguished name components for equality 
388
- * @return 0 if a match
389
- */
390
-static int asn1_compare_dn_comp(const char *dn1, const char *dn2)
391
-{
392
-    int ret = 1;
393
-
394
-    if ((dn1 && dn2 == NULL) || (dn1 == NULL && dn2)) goto err_no_match;
395
-
396
-    ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 0;
397
-
398
-err_no_match:
399
-    return ret;
400
-}
401
-
402
-/**
403
- * Clean up all of the CA certificates.
404
- */
405
-void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx)
406
-{
407
-    int i = 0;
408
-
409
-    while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
410
-    {
411
-        x509_free(ca_cert_ctx->cert[i]);
412
-        ca_cert_ctx->cert[i++] = NULL;
413
-    }
414
-
415
-    free(ca_cert_ctx);
416
-}
417
-
418
-/*
419
- * Compare 2 distinguished names for equality 
420
- * @return 0 if a match
421
- */
422
-static int asn1_compare_dn(char * const dn1[], char * const dn2[])
423
-{
424
-    int i;
425
-
426
-    for (i = 0; i < X509_NUM_DN_TYPES; i++)
427
-    {
428
-        if (asn1_compare_dn_comp(dn1[i], dn2[i]))
429
-        {
430
-            return 1;
431
-        }
432
-    }
433
-
434
-    return 0;       /* all good */
435
-}
436
-
437
-/**
438
- * Retrieve the signature from a certificate.
439
- */
440
-const uint8_t *x509_get_signature(const uint8_t *asn1_sig, int *len)
441
-{
442
-    int offset = 0;
443
-    const uint8_t *ptr = NULL;
444
-
445
-    if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 || 
446
-            asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
447
-        goto end_get_sig;
448
-
449
-    if (asn1_sig[offset++] != ASN1_OCTET_STRING)
450
-        goto end_get_sig;
451
-    *len = get_asn1_length(asn1_sig, &offset);
452
-    ptr = &asn1_sig[offset];          /* all ok */
453
-
454
-end_get_sig:
455
-    return ptr;
456
-}
457
-
458
-#endif
459
-
460
-/**
461
- * Read the signature type of the certificate. We only support RSA-MD5 and
462
- * RSA-SHA1 signature types.
463
- */
464
-static int asn1_signature_type(const uint8_t *cert, 
465
-                                int *offset, X509_CTX *x509_ctx)
466
-{
467
-    int ret = X509_NOT_OK, len;
468
-
469
-    if (cert[(*offset)++] != ASN1_OID)
470
-        goto end_check_sig;
471
-
472
-    len = get_asn1_length(cert, offset);
473
-
474
-    if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
475
-        goto end_check_sig;     /* unrecognised cert type */
476
-
477
-    x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
478
-
479
-    *offset += len;
480
-    if (asn1_skip_obj(cert, offset, ASN1_NULL))
481
-        goto end_check_sig;
482
-    ret = X509_OK;
483
-
484
-end_check_sig:
485
-    return ret;
486
-}
487
-
488
-/**
489
- * Construct a new x509 object.
490
- * @return 0 if ok. < 0 if there was a problem.
491
- */
492
-int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
493
-{
494
-    int begin_tbs, end_tbs;
495
-    int ret = X509_NOT_OK, offset = 0, cert_size = 0;
496
-    X509_CTX *x509_ctx;
497
-    BI_CTX *bi_ctx;
498
-
499
-    *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
500
-    x509_ctx = *ctx;
501
-
502
-    /* get the certificate size */
503
-    asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE); 
504
-
505
-    if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
506
-        goto end_cert;
507
-
508
-    begin_tbs = offset;         /* start of the tbs */
509
-    end_tbs = begin_tbs;        /* work out the end of the tbs */
510
-    asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE);
511
-
512
-    if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
513
-        goto end_cert;
514
-
515
-    if (cert[offset] == ASN1_EXPLICIT_TAG)   /* optional version */
516
-    {
517
-        if (asn1_version(cert, &offset, x509_ctx))
518
-            goto end_cert;
519
-    }
520
-
521
-    if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */ 
522
-            asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
523
-        goto end_cert;
524
-
525
-    /* make sure the signature is ok */
526
-    if (asn1_signature_type(cert, &offset, x509_ctx))
527
-    {
528
-        ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
529
-        goto end_cert;
530
-    }
531
-
532
-    if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) || 
533
-            asn1_validity(cert, &offset, x509_ctx) ||
534
-            asn1_name(cert, &offset, x509_ctx->cert_dn) ||
535
-            asn1_public_key(cert, &offset, x509_ctx))
536
-        goto end_cert;
537
-
538
-    bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
539
-
540
-#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
541
-    /* use the appropriate signature algorithm (either SHA1 or MD5) */
542
-    if (x509_ctx->sig_type == SIG_TYPE_MD5)
543
-    {
544
-        MD5_CTX md5_ctx;
545
-        uint8_t md5_dgst[MD5_SIZE];
546
-        MD5Init(&md5_ctx);
547
-        MD5Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
548
-        MD5Final(&md5_ctx, md5_dgst);
549
-        x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
550
-    }
551
-    else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
552
-    {
553
-        SHA1_CTX sha_ctx;
554
-        uint8_t sha_dgst[SHA1_SIZE];
555
-        SHA1Init(&sha_ctx);
556
-        SHA1Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
557
-        SHA1Final(&sha_ctx, sha_dgst);
558
-        x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
559
-    }
560
-
561
-    offset = end_tbs;   /* skip the v3 data */
562
-    if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) || 
563
-            asn1_signature(cert, &offset, x509_ctx))
564
-        goto end_cert;
565
-#endif
566
-
567
-    if (len)
568
-    {
569
-        *len = cert_size;
570
-    }
571
-
572
-    ret = X509_OK;
573
-end_cert:
574
-
575
-#ifdef CONFIG_SSL_FULL_MODE
576
-    if (ret)
577
-    {
578
-        printf("Error: Invalid X509 ASN.1 file\n");
579
-    }
580
-#endif
581
-
582
-    return ret;
583
-}
584
-
585
-/**
586
- * Free an X.509 object's resources.
587
- */
588
-void x509_free(X509_CTX *x509_ctx)
589
-{
590
-    X509_CTX *next;
591
-    int i;
592
-
593
-    if (x509_ctx == NULL)       /* if already null, then don't bother */
594
-        return;
595
-
596
-    for (i = 0; i < X509_NUM_DN_TYPES; i++)
597
-    {
598
-        free(x509_ctx->ca_cert_dn[i]);
599
-        free(x509_ctx->cert_dn[i]);
600
-    }
601
-
602
-    free(x509_ctx->signature);
603
-
604
-#ifdef CONFIG_SSL_CERT_VERIFICATION 
605
-    if (x509_ctx->digest)
606
-    {
607
-        bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
608
-    }
609
-#endif
610
-
611
-    RSA_free(x509_ctx->rsa_ctx);
612
-
613
-    next = x509_ctx->next;
614
-    free(x509_ctx);
615
-    x509_free(next);        /* clear the chain */
616
-}
617
-
618
-#ifdef CONFIG_SSL_CERT_VERIFICATION
619
-/**
620
- * Do some basic checks on the certificate chain.
621
- *
622
- * Certificate verification consists of a number of checks:
623
- * - A root certificate exists in the certificate store.
624
- * - The date of the certificate is after the start date.
625
- * - The date of the certificate is before the finish date.
626
- * - The certificate chain is valid.
627
- * - That the certificate(s) are not self-signed.
628
- * - The signature of the certificate is valid.
629
- */
630
-int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) 
631
-{
632
-    int ret = X509_OK, i = 0;
633
-    bigint *cert_sig;
634
-    X509_CTX *next_cert = NULL;
635
-    BI_CTX *ctx;
636
-    bigint *mod, *expn;
637
-    struct timeval tv;
638
-    int match_ca_cert = 0;
639
-
640
-    if (cert == NULL || ca_cert_ctx == NULL)
641
-    {
642
-        ret = X509_VFY_ERROR_NO_TRUSTED_CERT;       
643
-        goto end_verify;
644
-    }
645
-
646
-    /* last cert in the chain - look for a trusted cert */
647
-    if (cert->next == NULL)
648
-    {
649
-        while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
650
-        {
651
-            if (asn1_compare_dn(cert->ca_cert_dn,
652
-                                        ca_cert_ctx->cert[i]->cert_dn) == 0)
653
-            {
654
-                match_ca_cert = 1;
655
-                break;
656
-            }
657
-
658
-            i++;
659
-        }
660
-
661
-        if (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
662
-        {
663
-            next_cert = ca_cert_ctx->cert[i];
664
-        }
665
-        else    /* trusted cert not found */
666
-        {
667
-            ret = X509_VFY_ERROR_NO_TRUSTED_CERT;       
668
-            goto end_verify;
669
-        }
670
-    }
671
-    else
672
-    {
673
-        next_cert = cert->next;
674
-    }
675
-
676
-    gettimeofday(&tv, NULL);
677
-
678
-    /* check the not before date */
679
-    if (tv.tv_sec < cert->not_before)
680
-    {
681
-        ret = X509_VFY_ERROR_NOT_YET_VALID;
682
-        goto end_verify;
683
-    }
684
-
685
-    /* check the not after date */
686
-    if (tv.tv_sec > cert->not_after)
687
-    {
688
-        ret = X509_VFY_ERROR_EXPIRED;
689
-        goto end_verify;
690
-    }
691
-
692
-    /* check the chain integrity */
693
-    if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn))
694
-    {
695
-        ret = X509_VFY_ERROR_INVALID_CHAIN;
696
-        goto end_verify;
697
-    }
698
-
699
-    /* check for self-signing */
700
-    if (!match_ca_cert && asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
701
-    {
702
-        ret = X509_VFY_ERROR_SELF_SIGNED;
703
-        goto end_verify;
704
-    }
705
-
706
-    /* check the signature */
707
-    ctx = cert->rsa_ctx->bi_ctx;
708
-    mod = next_cert->rsa_ctx->m;
709
-    expn = next_cert->rsa_ctx->e;
710
-    cert_sig = RSA_sign_verify(ctx, cert->signature, cert->sig_len, 
711
-            bi_clone(ctx, mod), bi_clone(ctx, expn));
712
-
713
-    if (cert_sig)
714
-    {
715
-        ret = cert->digest ?    /* check the signature */
716
-            bi_compare(cert_sig, cert->digest) :
717
-            X509_VFY_ERROR_UNSUPPORTED_DIGEST;
718
-        bi_free(ctx, cert_sig);
719
-
720
-        if (ret)
721
-            goto end_verify;
722
-    }
723
-    else
724
-    {
725
-        ret = X509_VFY_ERROR_BAD_SIGNATURE;
726
-        goto end_verify;
727
-    }
728
-
729
-    /* go down the certificate chain using recursion. */
730
-    if (ret == 0 && cert->next)
731
-    {
732
-        ret = x509_verify(ca_cert_ctx, next_cert);
733
-    }
734
-
735
-end_verify:
736
-    return ret;
737
-}
738
-#endif
739
-
740
-#if defined (CONFIG_SSL_FULL_MODE)
741
-/**
742
- * Used for diagnostics.
743
- */
744
-void x509_print(CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) 
745
-{
746
-    if (cert == NULL)
747
-        return;
748
-
749
-    printf("----------------   CERT DEBUG   ----------------\n");
750
-    printf("* CA Cert Distinguished Name\n");
751
-    if (cert->ca_cert_dn[X509_COMMON_NAME])
752
-    {
753
-        printf("Common Name (CN):\t%s\n", cert->ca_cert_dn[X509_COMMON_NAME]);
754
-    }
755
-
756
-    if (cert->ca_cert_dn[X509_ORGANIZATION])
757
-    {
758
-        printf("Organization (O):\t%s\n", cert->ca_cert_dn[X509_ORGANIZATION]);
759
-    }
760
-
761
-    if (cert->ca_cert_dn[X509_ORGANIZATIONAL_TYPE])
762
-    {
763
-        printf("Organizational Unit (OU): %s\n", 
764
-                cert->ca_cert_dn[X509_ORGANIZATIONAL_TYPE]);
765
-    }
766
-
767
-    printf("* Cert Distinguished Name\n");
768
-    if (cert->cert_dn[X509_COMMON_NAME])
769
-    {
770
-        printf("Common Name (CN):\t%s\n", cert->cert_dn[X509_COMMON_NAME]);
771
-    }
772
-
773
-    if (cert->cert_dn[X509_ORGANIZATION])
774
-    {
775
-        printf("Organization (O):\t%s\n", cert->cert_dn[X509_ORGANIZATION]);
776
-    }
777
-
778
-    if (cert->cert_dn[X509_ORGANIZATIONAL_TYPE])
779
-    {
780
-        printf("Organizational Unit (OU): %s\n", 
781
-                cert->cert_dn[X509_ORGANIZATIONAL_TYPE]);
782
-    }
783
-
784
-    printf("Not Before:\t\t%s", ctime(&cert->not_before));
785
-    printf("Not After:\t\t%s", ctime(&cert->not_after));
786
-    printf("RSA bitsize:\t\t%d\n", cert->rsa_ctx->num_octets*8);
787
-    printf("Sig Type:\t\t");
788
-    switch (cert->sig_type)
789
-    {
790
-        case SIG_TYPE_MD5:
791
-            printf("MD5\n");
792
-            break;
793
-        case SIG_TYPE_SHA1:
794
-            printf("SHA1\n");
795
-            break;
796
-        case SIG_TYPE_MD2:
797
-            printf("MD2\n");
798
-            break;
799
-        default:
800
-            printf("Unrecognized: %d\n", cert->sig_type);
801
-            break;
802
-    }
803
-
804
-    printf("Verify:\t\t\t");
805
-
806
-    if (ca_cert_ctx)
807
-    {
808
-        x509_display_error(x509_verify(ca_cert_ctx, cert));
809
-    }
810
-
811
-    printf("\n");
812
-#if 0
813
-    print_blob("Signature", cert->signature, cert->sig_len);
814
-    bi_print("Modulus", cert->rsa_ctx->m);
815
-    bi_print("Pub Exp", cert->rsa_ctx->e);
816
-#endif
817
-
818
-    if (ca_cert_ctx)
819
-    {
820
-        x509_print(ca_cert_ctx, cert->next);
821
-    }
822
-}
823
-
824
-void x509_display_error(int error)
825
-{
826
-    switch (error)
827
-    {
828
-        case X509_NOT_OK:
829
-            printf("X509 not ok");
830
-            break;
831
-
832
-        case X509_VFY_ERROR_NO_TRUSTED_CERT:
833
-            printf("No trusted cert is available");
834
-            break;
835
-
836
-        case X509_VFY_ERROR_BAD_SIGNATURE:
837
-            printf("Bad signature");
838
-            break;
839
-
840
-        case X509_VFY_ERROR_NOT_YET_VALID:
841
-            printf("Cert is not yet valid");
842
-            break;
843
-
844
-        case X509_VFY_ERROR_EXPIRED:
845
-            printf("Cert has expired");
846
-            break;
847
-
848
-        case X509_VFY_ERROR_SELF_SIGNED:
849
-            printf("Cert is self-signed");
850
-            break;
851
-
852
-        case X509_VFY_ERROR_INVALID_CHAIN:
853
-            printf("Chain is invalid (check order of certs)");
854
-            break;
855
-
856
-        case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
857
-            printf("Unsupported digest");
858
-            break;
859
-
860
-        case X509_INVALID_PRIV_KEY:
861
-            printf("Invalid private key");
862
-            break;
863
-    }
864
-}
865
-#endif      /* CONFIG_SSL_FULL_MODE */
866
-
867
-#endif

+ 1
- 0
src/hci/strerror.c View File

@@ -120,4 +120,5 @@ struct errortab common_errors[] __errortab = {
120 120
 	{ ENOENT, "File not found" },
121 121
 	{ ENETUNREACH, "Network unreachable" },
122 122
 	{ ETIMEDOUT, "Connection timed out" },
123
+	{ EPIPE, "Broken pipe" },
123 124
 };

+ 11
- 10
src/include/gpxe/open.h View File

@@ -26,7 +26,9 @@ enum {
26 26
 	 *
27 27
 	 * Parameter list for open() is:
28 28
 	 *
29
-	 * 
29
+	 * int semantics;
30
+	 * struct sockaddr *peer;
31
+	 * struct sockaddr *local;
30 32
 	 */
31 33
 	LOCATION_SOCKET,
32 34
 };
@@ -44,9 +46,6 @@ struct uri_opener {
44 46
 	 * @v xfer		Data transfer interface
45 47
 	 * @v uri		URI
46 48
 	 * @ret rc		Return status code
47
-	 *
48
-	 * This method takes ownership of the URI structure, and is
49
-	 * responsible for eventually calling free_uri().
50 49
 	 */
51 50
 	int ( * open ) ( struct xfer_interface *xfer, struct uri *uri );
52 51
 };
@@ -56,10 +55,10 @@ struct uri_opener {
56 55
 
57 56
 /** A socket opener */
58 57
 struct socket_opener {
59
-	/** Communication domain (e.g. PF_INET) */
60
-	int domain;
61 58
 	/** Communication semantics (e.g. SOCK_STREAM) */
62
-	int type;
59
+	int semantics;
60
+	/** Address family (e.g. AF_INET) */
61
+	int family;
63 62
 	/** Open socket
64 63
 	 *
65 64
 	 * @v xfer		Data transfer interface
@@ -76,9 +75,11 @@ struct socket_opener {
76 75
 
77 76
 extern int xfer_open_uri ( struct xfer_interface *xfer,
78 77
 			   const char *uri_string );
79
-extern int xfer_open_socket ( struct xfer_interface *xfer,
80
-			      int domain, int type, struct sockaddr *peer,
81
-			      struct sockaddr *local );
78
+extern int xfer_open_named_socket ( struct xfer_interface *xfer,
79
+				    int semantics, struct sockaddr *peer,
80
+				    const char *name, struct sockaddr *local );
81
+extern int xfer_open_socket ( struct xfer_interface *xfer, int semantics,
82
+			      struct sockaddr *peer, struct sockaddr *local );
82 83
 extern int xfer_vopen ( struct xfer_interface *xfer, int type, va_list args );
83 84
 extern int xfer_open ( struct xfer_interface *xfer, int type, ... );
84 85
 

+ 37
- 4
src/include/gpxe/process.h View File

@@ -8,6 +8,7 @@
8 8
  */
9 9
 
10 10
 #include <gpxe/list.h>
11
+#include <gpxe/refcnt.h>
11 12
 
12 13
 /** A process */
13 14
 struct process {
@@ -19,14 +20,46 @@ struct process {
19 20
 	 * This method should execute a single step of the process.
20 21
 	 * Returning from this method is isomorphic to yielding the
21 22
 	 * CPU to another process.
22
-	 *
23
-	 * If the process wishes to be executed again, it must re-add
24
-	 * itself to the run queue using schedule().
25 23
 	 */
26 24
 	void ( * step ) ( struct process *process );
25
+	/** Reference counter
26
+	 *
27
+	 * If this interface is not part of a reference-counted
28
+	 * object, this field may be NULL.
29
+	 */
30
+	struct refcnt *refcnt;
27 31
 };
28 32
 
29
-extern void schedule ( struct process *process );
33
+extern void process_add ( struct process *process );
34
+extern void process_del ( struct process *process );
30 35
 extern void step ( void );
31 36
 
37
+/**
38
+ * Initialise process without adding to process list
39
+ *
40
+ * @v process		Process
41
+ * @v step		Process' step() method
42
+ */
43
+static inline __attribute__ (( always_inline )) void
44
+process_init_stopped ( struct process *process,
45
+		       void ( * step ) ( struct process *process ),
46
+		       struct refcnt *refcnt ) {
47
+	process->step = step;
48
+	process->refcnt = refcnt;
49
+}
50
+
51
+/**
52
+ * Initialise process and add to process list
53
+ *
54
+ * @v process		Process
55
+ * @v step		Process' step() method
56
+ */
57
+static inline __attribute__ (( always_inline )) void
58
+process_init ( struct process *process,
59
+	       void ( * step ) ( struct process *process ),
60
+	       struct refcnt *refcnt ) {
61
+	process_init_stopped ( process, step, refcnt );
62
+	process_add ( process );
63
+}
64
+
32 65
 #endif /* _GPXE_PROCESS_H */

+ 11
- 0
src/include/gpxe/retry.h View File

@@ -37,4 +37,15 @@ struct retry_timer {
37 37
 extern void start_timer ( struct retry_timer *timer );
38 38
 extern void stop_timer ( struct retry_timer *timer );
39 39
 
40
+/**
41
+ * Test to see if timer is currently running
42
+ *
43
+ * @v timer		Retry timer
44
+ * @ret running		Non-zero if timer is running
45
+ */
46
+static inline __attribute__ (( always_inline )) unsigned long
47
+timer_running ( struct retry_timer *timer ) {
48
+	return ( timer->start );
49
+}
50
+
40 51
 #endif /* _GPXE_RETRY_H */

+ 21
- 30
src/include/gpxe/socket.h View File

@@ -8,31 +8,7 @@
8 8
  */
9 9
 
10 10
 /**
11
- * @defgroup commdomains Communication domains
12
- *
13
- * @{
14
- */
15
-#define PF_INET		1	/**< IPv4 Internet protocols */
16
-#define PF_INET6	2	/**< IPv6 Internet protocols */
17
-/** @} */
18
-
19
-/**
20
- * Name communication domain
21
- *
22
- * @v domain		Communication domain (e.g. PF_INET)
23
- * @ret name		Name of communication domain
24
- */
25
-static inline __attribute__ (( always_inline )) const char *
26
-socket_domain_name ( int domain ) {
27
-	switch ( domain ) {
28
-	case PF_INET:		return "PF_INET";
29
-	case PF_INET6:		return "PF_INET6";
30
-	default:		return "PF_UNKNOWN";
31
-	}
32
-}
33
-
34
-/**
35
- * @defgroup commtypes Communication types
11
+ * @defgroup commtypes Communication semantics
36 12
  *
37 13
  * @{
38 14
  */
@@ -41,14 +17,14 @@ socket_domain_name ( int domain ) {
41 17
 /** @} */
42 18
 
43 19
 /**
44
- * Name communication type
20
+ * Name communication semantics
45 21
  *
46
- * @v type		Communication type (e.g. SOCK_STREAM)
47
- * @ret name		Name of communication type
22
+ * @v semantics		Communication semantics (e.g. SOCK_STREAM)
23
+ * @ret name		Name of communication semantics
48 24
  */
49 25
 static inline __attribute__ (( always_inline )) const char *
50
-socket_type_name ( int type ) {
51
-	switch ( type ) {
26
+socket_semantics_name ( int semantics ) {
27
+	switch ( semantics ) {
52 28
 	case SOCK_STREAM:	return "SOCK_STREAM";
53 29
 	case SOCK_DGRAM:	return "SOCK_DGRAM";
54 30
 	default:		return "SOCK_UNKNOWN";
@@ -64,6 +40,21 @@ socket_type_name ( int type ) {
64 40
 #define AF_INET6	2	/**< IPv6 Internet addresses */
65 41
 /** @} */
66 42
 
43
+/**
44
+ * Name address family
45
+ *
46
+ * @v family		Address family (e.g. AF_INET)
47
+ * @ret name		Name of address family
48
+ */
49
+static inline __attribute__ (( always_inline )) const char *
50
+socket_family_name ( int family ) {
51
+	switch ( family ) {
52
+	case AF_INET:		return "AF_INET";
53
+	case AF_INET6:		return "AF_INET6";
54
+	default:		return "AF_UNKNOWN";
55
+	}
56
+}
57
+
67 58
 /** A socket address family */
68 59
 typedef uint16_t sa_family_t;
69 60
 

+ 25
- 6
src/include/gpxe/uri.h View File

@@ -8,6 +8,7 @@
8 8
  */
9 9
 
10 10
 #include <stdlib.h>
11
+#include <gpxe/refcnt.h>
11 12
 
12 13
 /** A Uniform Resource Identifier
13 14
  *
@@ -37,6 +38,8 @@
37 38
  *   query = "what=is", fragment = "this"
38 39
  */
39 40
 struct uri {
41
+	/** Reference count */
42
+	struct refcnt refcnt;
40 43
 	/** Scheme */
41 44
 	const char *scheme;
42 45
 	/** Opaque part */
@@ -100,18 +103,34 @@ static inline int uri_has_relative_path ( struct uri *uri ) {
100 103
 }
101 104
 
102 105
 /**
103
- * Free URI structure
106
+ * Increment URI reference count
104 107
  *
105 108
  * @v uri		URI
109
+ * @ret uri		URI
110
+ */
111
+static inline __attribute__ (( always_inline )) struct uri *
112
+uri_get ( struct uri *uri ) {
113
+	ref_get ( &uri->refcnt );
114
+	return uri;
115
+}
116
+
117
+/**
118
+ * Decrement URI reference count
106 119
  *
107
- * Frees all the dynamically-allocated storage used by the URI
108
- * structure.
120
+ * @v uri		URI
109 121
  */
110
-static inline void free_uri ( struct uri *uri ) {
111
-	free ( uri );
122
+static inline __attribute__ (( always_inline )) void
123
+uri_put ( struct uri *uri ) {
124
+	ref_put ( &uri->refcnt );
112 125
 }
113 126
 
114 127
 extern struct uri * parse_uri ( const char *uri_string );
115
-unsigned int uri_port ( struct uri *uri, unsigned int default_port );
128
+extern unsigned int uri_port ( struct uri *uri, unsigned int default_port );
129
+extern int unparse_uri ( char *buf, size_t size, struct uri *uri );
130
+extern struct uri * uri_dup ( struct uri *uri );
131
+extern char * resolve_path ( const char *base_path,
132
+			     const char *relative_path );
133
+extern struct uri * resolve_uri ( struct uri *base_uri,
134
+				  struct uri *relative_uri );
116 135
 
117 136
 #endif /* _GPXE_URI_H */

+ 4
- 0
src/include/gpxe/vsprintf.h View File

@@ -64,4 +64,8 @@ struct printf_context {
64 64
 
65 65
 extern size_t vcprintf ( struct printf_context *ctx, const char *fmt,
66 66
 			 va_list args );
67
+extern int vssnprintf ( char *buf, ssize_t ssize, const char *fmt,
68
+			va_list args );
69
+extern int ssnprintf ( char *buf, ssize_t ssize, const char *fmt, ... );
70
+
67 71
 #endif /* _GPXE_VSPRINTF_H */

+ 19
- 1
src/include/gpxe/xfer.h View File

@@ -112,6 +112,20 @@ enum seek_whence {
112 112
 	SEEK_CUR,
113 113
 };
114 114
 
115
+/**
116
+ * Describe seek basis
117
+ *
118
+ * @v whence		Basis for new position
119
+ */
120
+static inline __attribute__ (( always_inline )) const char *
121
+whence_text ( int whence ) {
122
+	switch ( whence ) {
123
+	case SEEK_SET:	return "SET";
124
+	case SEEK_CUR:	return "CUR";
125
+	default:	return "INVALID";
126
+	}
127
+}
128
+
115 129
 extern struct xfer_interface null_xfer;
116 130
 extern struct xfer_interface_operations null_xfer_ops;
117 131
 
@@ -121,14 +135,18 @@ extern int xfer_vredirect ( struct xfer_interface *xfer, int type,
121 135
 extern int xfer_redirect ( struct xfer_interface *xfer, int type, ... );
122 136
 extern int xfer_request ( struct xfer_interface *xfer, off_t offset,
123 137
 			  int whence, size_t len );
124
-extern int xfer_request_all ( struct xfer_interface *xfer );
125 138
 extern int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence );
139
+extern int xfer_ready ( struct xfer_interface *xfer );
126 140
 extern struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer,
127 141
 					   size_t len );
128 142
 extern int xfer_deliver_iob ( struct xfer_interface *xfer,
129 143
 			      struct io_buffer *iobuf );
130 144
 extern int xfer_deliver_raw ( struct xfer_interface *xfer,
131 145
 			      const void *data, size_t len );
146
+extern int xfer_vprintf ( struct xfer_interface *xfer,
147
+			  const char *format, va_list args );
148
+extern int xfer_printf ( struct xfer_interface *xfer,
149
+			 const char *format, ... );
132 150
 
133 151
 extern void ignore_xfer_close ( struct xfer_interface *xfer, int rc );
134 152
 extern int ignore_xfer_vredirect ( struct xfer_interface *xfer,

+ 2
- 1
src/include/libgen.h View File

@@ -1,6 +1,7 @@
1 1
 #ifndef _LIBGEN_H
2 2
 #define _LIBGEN_H
3 3
 
4
-char * basename ( char *path );
4
+extern char * basename ( char *path );
5
+extern char * dirname ( char *path );
5 6
 
6 7
 #endif /* _LIBGEN_H */

+ 5
- 0
src/include/stdio.h View File

@@ -10,10 +10,15 @@ printf ( const char *fmt, ... );
10 10
 extern int __attribute__ (( format ( printf, 3, 4 ) ))
11 11
 snprintf ( char *buf, size_t size, const char *fmt, ... );
12 12
 
13
+extern int __attribute__ (( format ( printf, 2, 3 ) ))
14
+asprintf ( char **strp, const char *fmt, ... );
15
+
13 16
 extern int vprintf ( const char *fmt, va_list args );
14 17
 
15 18
 extern int vsnprintf ( char *buf, size_t size, const char *fmt, va_list args );
16 19
 
20
+extern int vasprintf ( char **strp, const char *fmt, va_list args );
21
+
17 22
 /**
18 23
  * Write a formatted string to a buffer
19 24
  *

+ 2
- 5
src/net/netdevice.c View File

@@ -388,7 +388,7 @@ int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
388 388
  * This polls all interfaces for received packets, and processes
389 389
  * packets from the RX queue.
390 390
  */
391
-static void net_step ( struct process *process ) {
391
+static void net_step ( struct process *process __unused ) {
392 392
 	struct net_device *netdev;
393 393
 	struct io_buffer *iobuf;
394 394
 
@@ -410,9 +410,6 @@ static void net_step ( struct process *process ) {
410 410
 			netdev->ll_protocol->rx ( iobuf, netdev );
411 411
 		}
412 412
 	}
413
-
414
-	/* Re-schedule ourself */
415
-	schedule ( process );
416 413
 }
417 414
 
418 415
 /** Networking stack process */
@@ -422,7 +419,7 @@ static struct process net_process = {
422 419
 
423 420
 /** Initialise the networking stack process */
424 421
 static void init_net ( void ) {
425
-	schedule ( &net_process );
422
+	process_add ( &net_process );
426 423
 }
427 424
 
428 425
 INIT_FN ( INIT_PROCESS, init_net, NULL, NULL );

+ 4
- 6
src/net/retry.c View File

@@ -64,7 +64,7 @@ static LIST_HEAD ( timers );
64 64
  * be stopped and the timer's callback function will be called.
65 65
  */
66 66
 void start_timer ( struct retry_timer *timer ) {
67
-	if ( ! timer->start )
67
+	if ( ! timer_running ( timer ) )
68 68
 		list_add ( &timer->list, &timers );
69 69
 	timer->start = currticks();
70 70
 	if ( timer->timeout < MIN_TIMEOUT )
@@ -86,7 +86,7 @@ void stop_timer ( struct retry_timer *timer ) {
86 86
 	unsigned long runtime;
87 87
 
88 88
 	/* If timer was already stopped, do nothing */
89
-	if ( ! timer->start )
89
+	if ( ! timer_running ( timer ) )
90 90
 		return;
91 91
 
92 92
 	list_del ( &timer->list );
@@ -153,7 +153,7 @@ static void timer_expired ( struct retry_timer *timer ) {
153 153
  *
154 154
  * @v process		Retry timer process
155 155
  */
156
-static void retry_step ( struct process *process ) {
156
+static void retry_step ( struct process *process __unused ) {
157 157
 	struct retry_timer *timer;
158 158
 	struct retry_timer *tmp;
159 159
 	unsigned long now = currticks();
@@ -164,8 +164,6 @@ static void retry_step ( struct process *process ) {
164 164
 		if ( used >= timer->timeout )
165 165
 			timer_expired ( timer );
166 166
 	}
167
-
168
-	schedule ( process );
169 167
 }
170 168
 
171 169
 /** Retry timer process */
@@ -175,7 +173,7 @@ static struct process retry_process = {
175 173
 
176 174
 /** Initialise the retry timer module */
177 175
 static void init_retry ( void ) {
178
-	schedule ( &retry_process );
176
+	process_add ( &retry_process );
179 177
 }
180 178
 
181 179
 INIT_FN ( INIT_PROCESS, init_retry, NULL, NULL );

+ 1
- 26
src/net/tcp/iscsi.c View File

@@ -23,6 +23,7 @@
23 23
 #include <errno.h>
24 24
 #include <assert.h>
25 25
 #include <byteswap.h>
26
+#include <gpxe/vsprintf.h>
26 27
 #include <gpxe/scsi.h>
27 28
 #include <gpxe/process.h>
28 29
 #include <gpxe/uaccess.h>
@@ -348,32 +349,6 @@ static void iscsi_tx_data_out ( struct iscsi_session *iscsi,
348 349
  *
349 350
  */
350 351
 
351
-/**
352
- * Version of snprintf() that accepts a signed buffer size
353
- *
354
- * @v buf		Buffer into which to write the string
355
- * @v size		Size of buffer
356
- * @v fmt		Format string
357
- * @v args		Arguments corresponding to the format string
358
- * @ret len		Length of formatted string
359
- *
360
- * This is a utility function for iscsi_build_login_request_strings().
361
- */
362
-static int ssnprintf ( char *buf, ssize_t ssize, const char *fmt, ... ) {
363
-	va_list args;
364
-	int len;
365
-
366
-	/* Treat negative buffer size as zero buffer size */
367
-	if ( ssize < 0 )
368
-		ssize = 0;
369
-
370
-	/* Hand off to vsnprintf */
371
-	va_start ( args, fmt );
372
-	len = vsnprintf ( buf, ssize, fmt, args );
373
-	va_end ( args );
374
-	return len;
375
-}
376
-
377 352
 /**
378 353
  * Build iSCSI login request strings
379 354
  *

+ 145
- 0
src/tests/uri_test.c View File

@@ -0,0 +1,145 @@
1
+#include <stdint.h>
2
+#include <stddef.h>
3
+#include <stdio.h>
4
+#include <string.h>
5
+#include <errno.h>
6
+#include <gpxe/uri.h>
7
+
8
+#define URI_MAX_LEN 1024
9
+
10
+struct uri_test {
11
+	const char *base_uri_string;
12
+	const char *relative_uri_string;
13
+	const char *resolved_uri_string;
14
+};
15
+
16
+static struct uri_test uri_tests[] = {
17
+	{ "http://www.fensystems.co.uk", "",
18
+	  "http://www.fensystems.co.uk/" },
19
+	{ "http://etherboot.org/wiki/page1", "page2",
20
+	  "http://etherboot.org/wiki/page2" },
21
+	{ "http://etherboot.org/wiki/page1", "../page3",
22
+	  "http://etherboot.org/page3" },
23
+	{ "tftp://192.168.0.1/", "/tftpboot/vmlinuz",
24
+	  "tftp://192.168.0.1/tftpboot/vmlinuz" },
25
+#if 0
26
+	"http://www.etherboot.org/wiki",
27
+	"mailto:bob@nowhere.com",
28
+	"ftp://joe:secret@insecure.org:8081/hidden/path/to?what=is#this",
29
+#endif
30
+};
31
+
32
+static int test_parse_unparse ( const char *uri_string ) {
33
+	char buf[URI_MAX_LEN];
34
+	size_t len;
35
+	struct uri *uri = NULL;
36
+	int rc;
37
+
38
+	/* Parse and unparse URI */
39
+	uri = parse_uri ( uri_string );
40
+	if ( ! uri ) {
41
+		rc = -ENOMEM;
42
+		goto done;
43
+	}
44
+	len = unparse_uri ( buf, sizeof ( buf ), uri );
45
+
46
+	/* Compare result */
47
+	if ( strcmp ( buf, uri_string ) != 0 ) {
48
+		printf ( "Unparse of \"%s\" produced \"%s\"\n",
49
+			 uri_string, buf );
50
+		rc = -EINVAL;
51
+		goto done;
52
+	}
53
+
54
+	rc = 0;
55
+
56
+ done:
57
+	uri_put ( uri );
58
+	if ( rc ) {
59
+		printf ( "URI parse-unparse of \"%s\" failed: %s\n",
60
+			 uri_string, strerror ( rc ) );
61
+	}
62
+	return rc;
63
+}
64
+
65
+static int test_resolve ( const char *base_uri_string,
66
+			  const char *relative_uri_string,
67
+			  const char *resolved_uri_string ) {
68
+	struct uri *base_uri = NULL;
69
+	struct uri *relative_uri = NULL;
70
+	struct uri *resolved_uri = NULL;
71
+	char buf[URI_MAX_LEN];
72
+	size_t len;
73
+	int rc;
74
+
75
+	/* Parse URIs */
76
+	base_uri = parse_uri ( base_uri_string );
77
+	if ( ! base_uri ) {
78
+		rc = -ENOMEM;
79
+		goto done;
80
+	}
81
+	relative_uri = parse_uri ( relative_uri_string );
82
+	if ( ! relative_uri ) {
83
+		rc = -ENOMEM;
84
+		goto done;
85
+	}
86
+
87
+	/* Resolve URI */
88
+	resolved_uri = resolve_uri ( base_uri, relative_uri );
89
+	if ( ! resolved_uri ) {
90
+		rc = -ENOMEM;
91
+		goto done;
92
+	}
93
+
94
+	/* Compare result */
95
+	len = unparse_uri ( buf, sizeof ( buf ), resolved_uri );
96
+	if ( strcmp ( buf, resolved_uri_string ) != 0 ) {
97
+		printf ( "Resolution of \"%s\"+\"%s\" produced \"%s\"\n",
98
+			 base_uri_string, relative_uri_string, buf );
99
+		rc = -EINVAL;
100
+		goto done;
101
+	}
102
+
103
+	rc = 0;
104
+
105
+ done:
106
+	uri_put ( base_uri );
107
+	uri_put ( relative_uri );
108
+	uri_put ( resolved_uri );
109
+	if ( rc ) {
110
+		printf ( "URI resolution of \"%s\"+\"%s\" failed: %s\n",
111
+			 base_uri_string, relative_uri_string,
112
+			 strerror ( rc ) );
113
+	}
114
+	return rc;
115
+}
116
+
117
+int uri_test ( void ) {
118
+	unsigned int i;
119
+	struct uri_test *uri_test;
120
+	int rc;
121
+	int overall_rc = 0;
122
+
123
+	for ( i = 0 ; i < ( sizeof ( uri_tests ) /
124
+			    sizeof ( uri_tests[0] ) ) ; i++ ) {
125
+		uri_test = &uri_tests[i];
126
+		rc = test_parse_unparse ( uri_test->base_uri_string );
127
+		if ( rc != 0 )
128
+			overall_rc = rc;
129
+		rc = test_parse_unparse ( uri_test->relative_uri_string );
130
+		if ( rc != 0 )
131
+			overall_rc = rc;
132
+		rc = test_parse_unparse ( uri_test->resolved_uri_string );
133
+		if ( rc != 0 )
134
+			overall_rc = rc;
135
+		rc = test_resolve ( uri_test->base_uri_string,
136
+				    uri_test->relative_uri_string,
137
+				    uri_test->resolved_uri_string );
138
+		if ( rc != 0 )
139
+			overall_rc = rc;
140
+	}
141
+
142
+	if ( overall_rc )
143
+		printf ( "URI tests failed: %s\n", strerror ( overall_rc ) );
144
+	return overall_rc;
145
+}

Loading…
Cancel
Save