iPXE
Functions
uri.c File Reference

Uniform Resource Identifiers. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <ctype.h>
#include <ipxe/vsprintf.h>
#include <ipxe/params.h>
#include <ipxe/tcpip.h>
#include <ipxe/uri.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
 FILE_SECBOOT (PERMITTED)
 
size_t uri_decode (const char *encoded, void *buf, size_t len)
 Decode URI field. More...
 
static void uri_decode_inplace (char *encoded)
 Decode URI field in-place. More...
 
static int uri_character_escaped (char c, unsigned int field)
 Check if character should be escaped within a URI field. More...
 
size_t uri_encode (unsigned int field, const void *raw, size_t raw_len, char *buf, ssize_t len)
 Encode URI field. More...
 
size_t uri_encode_string (unsigned int field, const char *string, char *buf, ssize_t len)
 Encode URI field string. More...
 
static void uri_dump (const struct uri *uri)
 Dump URI for debugging. More...
 
static void uri_free (struct refcnt *refcnt)
 Free URI. More...
 
struct uriparse_uri (const char *uri_string)
 Parse URI. More...
 
unsigned int uri_port (const struct uri *uri, unsigned int default_port)
 Get port from URI. More...
 
size_t format_uri (const struct uri *uri, char *buf, size_t len)
 Format URI. More...
 
char * format_uri_alloc (const struct uri *uri)
 Format URI. More...
 
static size_t uri_copy_fields (const struct uri *src, struct uri *dest)
 Copy URI fields. More...
 
struct uriuri_dup (const struct uri *uri)
 Duplicate URI. More...
 
char * resolve_path (const char *base_path, const char *relative_path)
 Resolve base+relative path. More...
 
struct uriresolve_uri (const struct uri *base_uri, struct uri *relative_uri)
 Resolve base+relative URI. More...
 
static struct uritftp_uri (struct sockaddr *sa_server, const char *filename)
 Construct TFTP URI from server address and filename. More...
 
struct uripxe_uri (struct sockaddr *sa_server, const char *filename)
 Construct URI from server address and filename. More...
 

Detailed Description

Uniform Resource Identifiers.

Definition in file uri.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED  )

◆ uri_decode()

size_t uri_decode ( const char *  encoded,
void *  buf,
size_t  len 
)

Decode URI field.

Parameters
encodedEncoded field
bufData buffer
lenLength
Return values
lenLength of data

URI decoding can never increase the length of a string; we can therefore safely decode in place.

Definition at line 54 of file uri.c.

54  {
55  uint8_t *out = buf;
56  unsigned int count = 0;
57  char hexbuf[3];
58  char *hexbuf_end;
59  char c;
60  char decoded;
61  unsigned int skip;
62 
63  /* Copy string, decoding escaped characters as necessary */
64  while ( ( c = *(encoded++) ) ) {
65  if ( c == '%' ) {
66  snprintf ( hexbuf, sizeof ( hexbuf ), "%s", encoded );
67  decoded = strtoul ( hexbuf, &hexbuf_end, 16 );
68  skip = ( hexbuf_end - hexbuf );
69  encoded += skip;
70  if ( skip )
71  c = decoded;
72  }
73  if ( count < len )
74  out[count] = c;
75  count++;
76  }
77  return count;
78 }
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition: string.c:485
__be32 out[4]
Definition: CIB_PRM.h:36
ring len
Length.
Definition: dwmac.h:231
static unsigned int count
Number of entries.
Definition: dwmac.h:225
unsigned char uint8_t
Definition: stdint.h:10
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:383

References count, len, out, snprintf(), and strtoul().

Referenced by parse_uristring_setting(), and uri_decode_inplace().

◆ uri_decode_inplace()

static void uri_decode_inplace ( char *  encoded)
static

Decode URI field in-place.

Parameters
encodedEncoded field, or NULL

Definition at line 85 of file uri.c.

85  {
86  char *decoded = encoded;
87  size_t len;
88 
89  /* Do nothing if field is not present */
90  if ( ! encoded )
91  return;
92 
93  /* Decode field in place */
94  len = uri_decode ( encoded, decoded, strlen ( encoded ) );
95 
96  /* Terminate decoded string */
97  decoded[len] = '\0';
98 }
ring len
Length.
Definition: dwmac.h:231
size_t uri_decode(const char *encoded, void *buf, size_t len)
Decode URI field.
Definition: uri.c:54
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244

References len, strlen(), and uri_decode().

Referenced by parse_uri(), and resolve_uri().

◆ uri_character_escaped()

static int uri_character_escaped ( char  c,
unsigned int  field 
)
static

Check if character should be escaped within a URI field.

Parameters
cCharacter
fieldURI field index
Return values
escapedCharacter should be escaped

Definition at line 107 of file uri.c.

107  {
108 
109  /* Non-printing characters and whitespace should always be
110  * escaped, since they cannot sensibly be displayed as part of
111  * a coherent URL string. (This test also catches control
112  * characters such as CR and LF, which could affect the
113  * operation of line-based protocols such as HTTP.)
114  *
115  * We should also escape characters which would alter the
116  * interpretation of the URL if not escaped, i.e. characters
117  * which have significance to the URL parser. We should not
118  * blindly escape all such characters, because this would lead
119  * to some very strange-looking URLs (e.g. if we were to
120  * always escape '/' as "%2F" even within the URI path).
121  *
122  * We do not need to be perfect. Our primary role is as a
123  * consumer of URIs rather than a producer; the main situation
124  * in which we produce a URI string is for display to a human
125  * user, who can probably tolerate some variance from the
126  * formal specification. The only situation in which we
127  * currently produce a URI string to be consumed by a computer
128  * is when constructing an HTTP request URI, which contains
129  * only the path and query fields.
130  *
131  * We can therefore sacrifice some correctness for the sake of
132  * code size. For example, colons within the URI host should
133  * be escaped unless they form part of an IPv6 literal
134  * address; doing this correctly would require the URI
135  * formatter to be aware of whether or not the URI host
136  * contained an IPv4 address, an IPv6 address, or a host name.
137  * We choose to simplify and never escape colons within the
138  * URI host field: in the event of a pathological hostname
139  * containing colons, this could potentially produce a URI
140  * string which could not be reparsed.
141  *
142  * After excluding non-printing characters, whitespace, and
143  * '%', the full set of characters with significance to the
144  * URL parser is "/#:@?". We choose for each URI field which
145  * of these require escaping in our use cases.
146  *
147  * For the scheme field (equivalently, if field is zero), we
148  * escape anything that has significance not just for our URI
149  * parser but for any other URI parsers (e.g. HTTP query
150  * string parsers, which care about '=' and '&').
151  */
152  static const char *escaped[URI_EPATH] = {
153  /* Scheme or default: escape everything */
154  [URI_SCHEME] = "/#:@?=&",
155  /* Opaque part: escape characters which would affect
156  * the reparsing of the URI, allowing everything else
157  * (e.g. ':', which will appear in iSCSI URIs).
158  */
159  [URI_OPAQUE] = "#",
160  /* User name: escape everything */
161  [URI_USER] = "/#:@?",
162  /* Password: escape everything */
163  [URI_PASSWORD] = "/#:@?",
164  /* Host name: escape everything except ':', which may
165  * appear as part of an IPv6 literal address.
166  */
167  [URI_HOST] = "/#@?",
168  /* Port number: escape everything */
169  [URI_PORT] = "/#:@?",
170  /* Path: escape everything except '/', which usually
171  * appears within paths.
172  */
173  [URI_PATH] = "#:@?",
174  };
175 
176  /* Always escape non-printing characters and whitespace */
177  if ( ( ! isprint ( c ) ) || ( c == ' ' ) )
178  return 1;
179 
180  /* Escape nothing else in already-escaped fields */
181  if ( field >= URI_EPATH )
182  return 0;
183 
184  /* Escape '%' and any field-specific characters */
185  if ( ( c == '%' ) || strchr ( escaped[field], c ) )
186  return 1;
187 
188  return 0;
189 }
Definition: uri.h:117
Definition: uri.h:118
static int isprint(int character)
Check if character is printable.
Definition: ctype.h:98
Definition: uri.h:119
char * strchr(const char *src, int character)
Find character within a string.
Definition: string.c:272
Definition: uri.h:115
Definition: uri.h:120

References isprint(), strchr(), URI_EPATH, URI_HOST, URI_OPAQUE, URI_PASSWORD, URI_PATH, URI_PORT, URI_SCHEME, and URI_USER.

Referenced by uri_encode().

◆ uri_encode()

size_t uri_encode ( unsigned int  field,
const void *  raw,
size_t  raw_len,
char *  buf,
ssize_t  len 
)

Encode URI field.

Parameters
fieldURI field index
rawRaw data
raw_lenLength of raw data
bufBuffer
lenLength of buffer
Return values
lenLength of encoded string (excluding NUL)

Definition at line 201 of file uri.c.

202  {
203  const uint8_t *raw_bytes = ( ( const uint8_t * ) raw );
204  ssize_t remaining = len;
205  size_t used;
206  char c;
207 
208  /* Ensure encoded string is NUL-terminated even if empty */
209  if ( len > 0 )
210  buf[0] = '\0';
211 
212  /* Copy string, escaping as necessary */
213  while ( raw_len-- ) {
214  c = *(raw_bytes++);
215  if ( uri_character_escaped ( c, field ) ) {
216  used = ssnprintf ( buf, remaining, "%%%02X", c );
217  } else {
218  used = ssnprintf ( buf, remaining, "%c", c );
219  }
220  buf += used;
221  remaining -= used;
222  }
223 
224  return ( len - remaining );
225 }
int ssnprintf(char *buf, ssize_t ssize, const char *fmt,...)
Version of vsnprintf() that accepts a signed buffer size.
Definition: vsprintf.c:421
ring len
Length.
Definition: dwmac.h:231
static size_t raw_len
Definition: base16.h:54
static int uri_character_escaped(char c, unsigned int field)
Check if character should be escaped within a URI field.
Definition: uri.c:107
unsigned char uint8_t
Definition: stdint.h:10
__be32 raw[7]
Definition: CIB_PRM.h:28
signed long ssize_t
Definition: stdint.h:7

References len, raw, raw_len, ssnprintf(), and uri_character_escaped().

Referenced by format_uristring_setting(), ocsp_uri_string(), and uri_encode_string().

◆ uri_encode_string()

size_t uri_encode_string ( unsigned int  field,
const char *  string,
char *  buf,
ssize_t  len 
)

Encode URI field string.

Parameters
fieldURI field index
stringString
bufBuffer
lenLength of buffer
Return values
lenLength of encoded string (excluding NUL)

Definition at line 236 of file uri.c.

237  {
238 
239  return uri_encode ( field, string, strlen ( string ), buf, len );
240 }
size_t uri_encode(unsigned int field, const void *raw, size_t raw_len, char *buf, ssize_t len)
Encode URI field.
Definition: uri.c:201
ring len
Length.
Definition: dwmac.h:231
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244

References len, strlen(), and uri_encode().

Referenced by format_uri(), and http_form_params().

◆ uri_dump()

static void uri_dump ( const struct uri uri)
static

Dump URI for debugging.

Parameters
uriURI

Definition at line 247 of file uri.c.

247  {
248 
249  if ( ! uri )
250  return;
251  if ( uri->scheme )
252  DBGC ( uri, " scheme \"%s\"", uri->scheme );
253  if ( uri->opaque )
254  DBGC ( uri, " opaque \"%s\"", uri->opaque );
255  if ( uri->user )
256  DBGC ( uri, " user \"%s\"", uri->user );
257  if ( uri->password )
258  DBGC ( uri, " password \"%s\"", uri->password );
259  if ( uri->host )
260  DBGC ( uri, " host \"%s\"", uri->host );
261  if ( uri->port )
262  DBGC ( uri, " port \"%s\"", uri->port );
263  if ( uri->path )
264  DBGC ( uri, " path \"%s\"", uri->path );
265  if ( uri->epath )
266  DBGC ( uri, " epath \"%s\"", uri->epath );
267  if ( uri->equery )
268  DBGC ( uri, " equery \"%s\"", uri->equery );
269  if ( uri->efragment )
270  DBGC ( uri, " efragment \"%s\"", uri->efragment );
271  if ( uri->params )
272  DBGC ( uri, " params \"%s\"", uri->params->name );
273 }
const char * equery
Query (with original URI encoding)
Definition: uri.h:85
#define DBGC(...)
Definition: compiler.h:505
const char * port
Port number.
Definition: uri.h:79
const char * scheme
Scheme.
Definition: uri.h:69
const char * path
Path (after URI decoding)
Definition: uri.h:81
struct parameters * params
Request parameters.
Definition: uri.h:89
const char * name
Name.
Definition: params.h:23
const char * host
Host name.
Definition: uri.h:77
const char * efragment
Fragment (with original URI encoding)
Definition: uri.h:87
const char * opaque
Opaque part.
Definition: uri.h:71
const char * password
Password.
Definition: uri.h:75
const char * epath
Path (with original URI encoding)
Definition: uri.h:83
const char * user
User name.
Definition: uri.h:73
A Uniform Resource Identifier.
Definition: uri.h:65

References DBGC, uri::efragment, uri::epath, uri::equery, uri::host, parameters::name, uri::opaque, uri::params, uri::password, uri::path, uri::port, uri::scheme, and uri::user.

Referenced by format_uri(), parse_uri(), and uri_dup().

◆ uri_free()

static void uri_free ( struct refcnt refcnt)
static

Free URI.

Parameters
refcntReference count

Definition at line 280 of file uri.c.

280  {
281  struct uri *uri = container_of ( refcnt, struct uri, refcnt );
282 
283  params_put ( uri->params );
284  free ( uri );
285 }
A reference counter.
Definition: refcnt.h:27
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:36
struct parameters * params
Request parameters.
Definition: uri.h:89
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
A Uniform Resource Identifier.
Definition: uri.h:65

References container_of, free, and uri::params.

Referenced by parse_uri(), and uri_dup().

◆ parse_uri()

struct uri* parse_uri ( const char *  uri_string)

Parse URI.

Parameters
uri_stringURI as a string
Return values
uriURI

Splits a URI into its component parts. The return URI structure is dynamically allocated and must eventually be freed by calling uri_put().

Definition at line 297 of file uri.c.

297  {
298  struct uri *uri;
299  struct parameters *params;
300  char *raw;
301  char *tmp;
302  char *path;
303  char *epath;
304  char *authority;
305  size_t raw_len;
306  unsigned int field;
307 
308  /* Allocate space for URI struct and two copies of the string */
309  raw_len = ( strlen ( uri_string ) + 1 /* NUL */ );
310  uri = zalloc ( sizeof ( *uri ) + ( 2 * raw_len ) );
311  if ( ! uri )
312  return NULL;
313  ref_init ( &uri->refcnt, uri_free );
314  raw = ( ( ( void * ) uri ) + sizeof ( *uri ) );
315  path = ( raw + raw_len );
316 
317  /* Copy in the raw string */
318  memcpy ( raw, uri_string, raw_len );
319 
320  /* Identify the parameter list, if present */
321  if ( ( tmp = strstr ( raw, "##params" ) ) ) {
322  *tmp = '\0';
323  tmp += 8 /* "##params" */;
324  params = find_parameters ( *tmp ? ( tmp + 1 ) : NULL );
325  if ( params ) {
326  uri->params = claim_parameters ( params );
327  } else {
328  /* Ignore non-existent submission blocks */
329  }
330  }
331 
332  /* Chop off the fragment, if it exists */
333  if ( ( tmp = strchr ( raw, '#' ) ) ) {
334  *(tmp++) = '\0';
335  uri->efragment = tmp;
336  }
337 
338  /* Identify absolute URIs */
339  epath = raw;
340  for ( tmp = raw ; ; tmp++ ) {
341  /* Possible scheme character (for our URI schemes) */
342  if ( isalpha ( *tmp ) || ( *tmp == '-' ) || ( *tmp == '_' ) )
343  continue;
344  /* Invalid scheme character or NUL: is a relative URI */
345  if ( *tmp != ':' )
346  break;
347  /* Absolute URI: identify hierarchical/opaque */
348  uri->scheme = raw;
349  *(tmp++) = '\0';
350  if ( *tmp == '/' ) {
351  /* Absolute URI with hierarchical part */
352  epath = tmp;
353  } else {
354  /* Absolute URI with opaque part */
355  uri->opaque = tmp;
356  epath = NULL;
357  }
358  break;
359  }
360 
361  /* If we don't have a path (i.e. we have an absolute URI with
362  * an opaque portion, we're already finished processing
363  */
364  if ( ! epath )
365  goto done;
366 
367  /* Chop off the query, if it exists */
368  if ( ( tmp = strchr ( epath, '?' ) ) ) {
369  *(tmp++) = '\0';
370  uri->equery = tmp;
371  }
372 
373  /* If we have no path remaining, then we're already finished
374  * processing.
375  */
376  if ( ! epath[0] )
377  goto done;
378 
379  /* Identify net/absolute/relative path */
380  if ( uri->scheme && ( strncmp ( epath, "//", 2 ) == 0 ) ) {
381  /* Net path. If this is terminated by the first '/'
382  * of an absolute path, then we have no space for a
383  * terminator after the authority field, so shuffle
384  * the authority down by one byte, overwriting one of
385  * the two slashes.
386  */
387  authority = ( epath + 2 );
388  if ( ( tmp = strchr ( authority, '/' ) ) ) {
389  /* Shuffle down */
390  uri->epath = tmp;
391  memmove ( ( authority - 1 ), authority,
392  ( tmp - authority ) );
393  authority--;
394  *(--tmp) = '\0';
395  }
396  } else {
397  /* Absolute/relative path */
398  uri->epath = epath;
399  authority = NULL;
400  }
401 
402  /* Create copy of path for decoding */
403  if ( uri->epath ) {
404  strcpy ( path, uri->epath );
405  uri->path = path;
406  }
407 
408  /* If we don't have an authority (i.e. we have a non-net
409  * path), we're already finished processing
410  */
411  if ( ! authority )
412  goto done;
413 
414  /* Split authority into user[:password] and host[:port] portions */
415  if ( ( tmp = strchr ( authority, '@' ) ) ) {
416  /* Has user[:password] */
417  *(tmp++) = '\0';
418  uri->host = tmp;
419  uri->user = authority;
420  if ( ( tmp = strchr ( authority, ':' ) ) ) {
421  /* Has password */
422  *(tmp++) = '\0';
423  uri->password = tmp;
424  }
425  } else {
426  /* No user:password */
427  uri->host = authority;
428  }
429 
430  /* Split host into host[:port] */
431  if ( ( tmp = strrchr ( uri->host, ':' ) ) &&
432  ( uri->host[ strlen ( uri->host ) - 1 ] != ']' ) ) {
433  *(tmp++) = '\0';
434  uri->port = tmp;
435  }
436 
437  done:
438  /* Decode fields in-place */
439  for ( field = 0 ; field < URI_EPATH ; field++ )
440  uri_decode_inplace ( ( char * ) uri_field ( uri, field ) );
441 
442  DBGC ( uri, "URI parsed \"%s\" to", uri_string );
443  uri_dump ( uri );
444  DBGC ( uri, "\n" );
445 
446  return uri;
447 }
const char * equery
Query (with original URI encoding)
Definition: uri.h:85
static void uri_dump(const struct uri *uri)
Dump URI for debugging.
Definition: uri.c:247
char * strrchr(const char *src, int character)
Find rightmost character within a string.
Definition: string.c:290
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:65
A request parameter list.
Definition: params.h:17
#define DBGC(...)
Definition: compiler.h:505
static int isalpha(int character)
Check if character is alphabetic.
Definition: ctype.h:76
struct parameters * find_parameters(const char *name)
Find request parameter list by name.
Definition: params.c:69
int strncmp(const char *first, const char *second, size_t max)
Compare strings.
Definition: string.c:187
const char * port
Port number.
Definition: uri.h:79
unsigned long tmp
Definition: linux_pci.h:65
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition: string.c:310
const char * scheme
Scheme.
Definition: uri.h:69
void * memcpy(void *dest, const void *src, size_t len) __nonnull
const char * path
Path (after URI decoding)
Definition: uri.h:81
char * strcpy(char *dest, const char *src)
Copy string.
Definition: string.c:347
struct parameters * params
Request parameters.
Definition: uri.h:89
static void uri_decode_inplace(char *encoded)
Decode URI field in-place.
Definition: uri.c:85
static size_t raw_len
Definition: base16.h:54
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
char * strchr(const char *src, int character)
Find character within a string.
Definition: string.c:272
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244
const char * host
Host name.
Definition: uri.h:77
void * memmove(void *dest, const void *src, size_t len) __nonnull
Definition: uri.h:120
const char * efragment
Fragment (with original URI encoding)
Definition: uri.h:87
#define uri_field(uri, field)
Access URI field.
Definition: uri.h:99
const char * opaque
Opaque part.
Definition: uri.h:71
struct refcnt refcnt
Reference count.
Definition: uri.h:67
static void uri_free(struct refcnt *refcnt)
Free URI.
Definition: uri.c:280
const char * password
Password.
Definition: uri.h:75
const char * epath
Path (with original URI encoding)
Definition: uri.h:83
__be32 raw[7]
Definition: CIB_PRM.h:28
const char * user
User name.
Definition: uri.h:73
A Uniform Resource Identifier.
Definition: uri.h:65
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
struct bofm_section_header done
Definition: bofm_test.c:46

References DBGC, done, uri::efragment, uri::epath, uri::equery, find_parameters(), uri::host, isalpha(), memcpy(), memmove(), NULL, uri::opaque, uri::params, uri::password, uri::path, uri::port, raw, raw_len, ref_init, uri::refcnt, uri::scheme, strchr(), strcpy(), strlen(), strncmp(), strrchr(), strstr(), tmp, uri_decode_inplace(), uri_dump(), URI_EPATH, uri_field, uri_free(), uri::user, and zalloc().

Referenced by cwuri_fetch_uri(), efi_path_uri(), fetch_root_path(), http_redirect(), imgdownload_string(), peerblk_retrieval_uri(), pxe_uri(), sanboot_core_exec(), tftp_apply_settings(), uri_churi_okx(), uri_params_okx(), uri_parse_okx(), uri_port_okx(), uri_resolve_okx(), and xfer_open_uri_string().

◆ uri_port()

unsigned int uri_port ( const struct uri uri,
unsigned int  default_port 
)

Get port from URI.

Parameters
uriURI, or NULL
default_portDefault port to use if none specified in URI
Return values
portPort

Definition at line 456 of file uri.c.

456  {
457 
458  if ( ( ! uri ) || ( ! uri->port ) )
459  return default_port;
460 
461  return ( strtoul ( uri->port, NULL, 0 ) );
462 }
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition: string.c:485
const char * port
Port number.
Definition: uri.h:79
A Uniform Resource Identifier.
Definition: uri.h:65
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322

References NULL, uri::port, and strtoul().

Referenced by ftp_open(), http_connect(), slam_open(), tcp_open_uri(), tftp_core_open(), udp_open_uri(), and uri_port_okx().

◆ format_uri()

size_t format_uri ( const struct uri uri,
char *  buf,
size_t  len 
)

Format URI.

Parameters
uriURI
bufBuffer to fill with URI string
sizeSize of buffer
Return values
lenLength of URI string

Definition at line 472 of file uri.c.

472  {
473  static const char prefixes[URI_FIELDS] = {
474  [URI_PASSWORD] = ':',
475  [URI_PORT] = ':',
476  [URI_EQUERY] = '?',
477  [URI_EFRAGMENT] = '#',
478  };
479  char prefix;
480  size_t used = 0;
481  unsigned int field;
482 
483  /* Ensure buffer is NUL-terminated */
484  if ( len )
485  buf[0] = '\0';
486 
487  /* Special-case NULL URI */
488  if ( ! uri )
489  return 0;
490 
491  /* Generate fields */
492  for ( field = 0 ; field < URI_FIELDS ; field++ ) {
493 
494  /* Skip non-existent fields */
495  if ( ! uri_field ( uri, field ) )
496  continue;
497 
498  /* Skip path field if encoded path is present */
499  if ( ( field == URI_PATH ) && uri->epath )
500  continue;
501 
502  /* Prefix this field, if applicable */
503  prefix = prefixes[field];
504  if ( ( field == URI_HOST ) && ( uri->user != NULL ) )
505  prefix = '@';
506  if ( prefix ) {
507  used += ssnprintf ( ( buf + used ), ( len - used ),
508  "%c", prefix );
509  }
510 
511  /* Encode this field */
512  used += uri_encode_string ( field, uri_field ( uri, field ),
513  ( buf + used ), ( len - used ) );
514 
515  /* Suffix this field, if applicable */
516  if ( field == URI_SCHEME ) {
517  used += ssnprintf ( ( buf + used ), ( len - used ),
518  ":%s", ( uri->host ? "//" : "" ) );
519  }
520  }
521 
522  if ( len ) {
523  DBGC ( uri, "URI formatted" );
524  uri_dump ( uri );
525  DBGC ( uri, " to \"%s%s\"\n", buf,
526  ( ( used > len ) ? "<TRUNCATED>" : "" ) );
527  }
528 
529  return used;
530 }
Definition: uri.h:117
size_t uri_encode_string(unsigned int field, const char *string, char *buf, ssize_t len)
Encode URI field string.
Definition: uri.c:236
static void uri_dump(const struct uri *uri)
Dump URI for debugging.
Definition: uri.c:247
#define DBGC(...)
Definition: compiler.h:505
char prefix[4]
Definition: vmconsole.c:53
Definition: uri.h:118
int ssnprintf(char *buf, ssize_t ssize, const char *fmt,...)
Version of vsnprintf() that accepts a signed buffer size.
Definition: vsprintf.c:421
Definition: uri.h:119
ring len
Length.
Definition: dwmac.h:231
const char * host
Host name.
Definition: uri.h:77
#define uri_field(uri, field)
Access URI field.
Definition: uri.h:99
const char * epath
Path (with original URI encoding)
Definition: uri.h:83
const char * user
User name.
Definition: uri.h:73
A Uniform Resource Identifier.
Definition: uri.h:65
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322

References DBGC, uri::epath, uri::host, len, NULL, prefix, ssnprintf(), uri_dump(), URI_EFRAGMENT, uri_encode_string(), URI_EQUERY, uri_field, URI_FIELDS, URI_HOST, URI_PASSWORD, URI_PATH, URI_PORT, URI_SCHEME, and uri::user.

Referenced by efi_uri_path(), format_uri_alloc(), http_open(), multiboot_add_cmdline(), uri_format_okx(), and uri_pxe_okx().

◆ format_uri_alloc()

char* format_uri_alloc ( const struct uri uri)

Format URI.

Parameters
uriURI
Return values
stringURI string, or NULL on failure

The caller is responsible for eventually freeing the allocated memory.

Definition at line 541 of file uri.c.

541  {
542  size_t len;
543  char *string;
544 
545  len = ( format_uri ( uri, NULL, 0 ) + 1 /* NUL */ );
546  string = malloc ( len );
547  if ( string )
548  format_uri ( uri, string, len );
549  return string;
550 }
uint32_t string
Definition: multiboot.h:14
ring len
Length.
Definition: dwmac.h:231
size_t format_uri(const struct uri *uri, char *buf, size_t len)
Format URI.
Definition: uri.c:472
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:621
A Uniform Resource Identifier.
Definition: uri.h:65
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322

References format_uri(), len, malloc(), NULL, and string.

Referenced by cwuri_fetch_uri(), imgdownload(), uri_churi_okx(), uri_format_okx(), and uri_resolve_okx().

◆ uri_copy_fields()

static size_t uri_copy_fields ( const struct uri src,
struct uri dest 
)
static

Copy URI fields.

Parameters
srcSource URI
destDestination URI, or NULL to calculate length
Return values
lenLength of raw URI

Definition at line 559 of file uri.c.

559  {
560  size_t len = sizeof ( *dest );
561  char *out = ( ( void * ) dest + len );
562  unsigned int field;
563  size_t field_len;
564 
565  /* Copy existent fields */
566  for ( field = 0 ; field < URI_FIELDS ; field++ ) {
567 
568  /* Skip non-existent fields */
569  if ( ! uri_field ( src, field ) )
570  continue;
571 
572  /* Calculate field length */
573  field_len = ( strlen ( uri_field ( src, field ) )
574  + 1 /* NUL */ );
575  len += field_len;
576 
577  /* Copy field, if applicable */
578  if ( dest ) {
579  memcpy ( out, uri_field ( src, field ), field_len );
580  uri_field ( dest, field ) = out;
581  out += field_len;
582  }
583  }
584  return len;
585 }
__be32 out[4]
Definition: CIB_PRM.h:36
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static const void * src
Definition: string.h:48
ring len
Length.
Definition: dwmac.h:231
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244
#define uri_field(uri, field)
Access URI field.
Definition: uri.h:99
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:151

References dest, len, memcpy(), out, src, strlen(), uri_field, and URI_FIELDS.

Referenced by uri_dup().

◆ uri_dup()

struct uri* uri_dup ( const struct uri uri)

Duplicate URI.

Parameters
uriURI
Return values
uriDuplicate URI

Creates a modifiable copy of a URI.

Definition at line 595 of file uri.c.

595  {
596  struct uri *dup;
597  size_t len;
598 
599  /* Allocate new URI */
600  len = uri_copy_fields ( uri, NULL );
601  dup = zalloc ( len );
602  if ( ! dup )
603  return NULL;
604  ref_init ( &dup->refcnt, uri_free );
605 
606  /* Copy fields */
607  uri_copy_fields ( uri, dup );
608 
609  /* Copy parameters */
610  dup->params = params_get ( uri->params );
611 
612  DBGC ( uri, "URI duplicated" );
613  uri_dump ( uri );
614  DBGC ( uri, "\n" );
615 
616  return dup;
617 }
static void uri_dump(const struct uri *uri)
Dump URI for debugging.
Definition: uri.c:247
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:65
#define DBGC(...)
Definition: compiler.h:505
static size_t uri_copy_fields(const struct uri *src, struct uri *dest)
Copy URI fields.
Definition: uri.c:559
ring len
Length.
Definition: dwmac.h:231
struct parameters * params
Request parameters.
Definition: uri.h:89
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
struct refcnt refcnt
Reference count.
Definition: uri.h:67
static void uri_free(struct refcnt *refcnt)
Free URI.
Definition: uri.c:280
A Uniform Resource Identifier.
Definition: uri.h:65
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322

References DBGC, len, NULL, uri::params, ref_init, uri::refcnt, uri_copy_fields(), uri_dump(), uri_free(), and zalloc().

Referenced by resolve_uri(), tftp_uri(), uri_dup_okx(), and uri_params_okx().

◆ resolve_path()

char* resolve_path ( const char *  base_path,
const char *  relative_path 
)

Resolve base+relative path.

Parameters
base_uriBase path
relative_uriRelative path
Return values
resolved_uriResolved path, or NULL on failure

Takes a base path (e.g. "/var/lib/tftpboot/vmlinuz" and a relative path (e.g. "initrd.gz") and produces a new path (e.g. "/var/lib/tftpboot/initrd.gz"). Note that any non-directory portion of the base path will automatically be stripped; this matches the semantics used when resolving the path component of URIs.

Definition at line 633 of file uri.c.

634  {
635  char *base_copy;
636  char *base_tmp;
637  char *resolved;
638 
639  /* If relative path is absolute, just re-use it */
640  if ( relative_path[0] == '/' )
641  return strdup ( relative_path );
642 
643  /* Create modifiable copy of path for dirname() */
644  base_copy = strdup ( base_path );
645  if ( ! base_copy )
646  return NULL;
647 
648  /* Strip filename portion of base path */
649  base_tmp = dirname ( base_copy );
650 
651  /* Process "./" and "../" elements */
652  while ( *relative_path == '.' ) {
653  relative_path++;
654  if ( *relative_path == 0 ) {
655  /* Do nothing */
656  } else if ( *relative_path == '/' ) {
657  relative_path++;
658  } else if ( *relative_path == '.' ) {
659  relative_path++;
660  if ( *relative_path == 0 ) {
661  base_tmp = dirname ( base_tmp );
662  } else if ( *relative_path == '/' ) {
663  base_tmp = dirname ( base_tmp );
664  relative_path++;
665  } else {
666  relative_path -= 2;
667  break;
668  }
669  } else {
670  relative_path--;
671  break;
672  }
673  }
674 
675  /* Create and return new path */
676  if ( asprintf ( &resolved, "%s%s%s", base_tmp,
677  ( ( base_tmp[ strlen ( base_tmp ) - 1 ] == '/' ) ?
678  "" : "/" ), relative_path ) < 0 )
679  resolved = NULL;
680  free ( base_copy );
681  return resolved;
682 }
char * dirname(char *path)
Return directory name from path.
Definition: basename.c:58
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
int asprintf(char **strp, const char *fmt,...)
Write a formatted string to newly allocated memory.
Definition: asprintf.c:42
char * strdup(const char *src)
Duplicate string.
Definition: string.c:394
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322

References asprintf(), dirname(), free, NULL, strdup(), and strlen().

Referenced by efi_local_open_path(), resolve_uri(), and uri_resolve_path_okx().

◆ resolve_uri()

struct uri* resolve_uri ( const struct uri base_uri,
struct uri relative_uri 
)

Resolve base+relative URI.

Parameters
base_uriBase URI, or NULL
relative_uriRelative URI
Return values
resolved_uriResolved URI, or NULL on failure

Takes a base URI (e.g. "http://ipxe.org/kernels/vmlinuz" and a relative URI (e.g. "../initrds/initrd.gz") and produces a new URI (e.g. "http://ipxe.org/initrds/initrd.gz").

Definition at line 695 of file uri.c.

696  {
697  struct uri tmp_uri;
698  char *tmp_epath = NULL;
699  char *tmp_path = NULL;
700  struct uri *new_uri;
701 
702  /* If relative URI is absolute, just re-use it */
703  if ( uri_is_absolute ( relative_uri ) || ( ! base_uri ) )
704  return uri_get ( relative_uri );
705 
706  /* Mangle URI */
707  memcpy ( &tmp_uri, base_uri, sizeof ( tmp_uri ) );
708  if ( relative_uri->epath ) {
709  tmp_epath = resolve_path ( ( base_uri->epath ?
710  base_uri->epath : "/" ),
711  relative_uri->epath );
712  if ( ! tmp_epath )
713  goto err_epath;
714  tmp_path = strdup ( tmp_epath );
715  if ( ! tmp_path )
716  goto err_path;
717  uri_decode_inplace ( tmp_path );
718  tmp_uri.epath = tmp_epath;
719  tmp_uri.path = tmp_path;
720  tmp_uri.equery = relative_uri->equery;
721  tmp_uri.efragment = relative_uri->efragment;
722  tmp_uri.params = relative_uri->params;
723  } else if ( relative_uri->equery ) {
724  tmp_uri.equery = relative_uri->equery;
725  tmp_uri.efragment = relative_uri->efragment;
726  tmp_uri.params = relative_uri->params;
727  } else if ( relative_uri->efragment ) {
728  tmp_uri.efragment = relative_uri->efragment;
729  tmp_uri.params = relative_uri->params;
730  } else if ( relative_uri->params ) {
731  tmp_uri.params = relative_uri->params;
732  }
733 
734  /* Create demangled URI */
735  new_uri = uri_dup ( &tmp_uri );
736  free ( tmp_path );
737  free ( tmp_epath );
738  return new_uri;
739 
740  free ( tmp_path );
741  err_path:
742  free ( tmp_epath );
743  err_epath:
744  return NULL;
745 }
const char * equery
Query (with original URI encoding)
Definition: uri.h:85
static struct uri * uri_get(struct uri *uri)
Increment URI reference count.
Definition: uri.h:195
static int uri_is_absolute(const struct uri *uri)
URI is an absolute URI.
Definition: uri.h:136
void * memcpy(void *dest, const void *src, size_t len) __nonnull
char * resolve_path(const char *base_path, const char *relative_path)
Resolve base+relative path.
Definition: uri.c:633
struct parameters * params
Request parameters.
Definition: uri.h:89
static void uri_decode_inplace(char *encoded)
Decode URI field in-place.
Definition: uri.c:85
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
struct uri * uri_dup(const struct uri *uri)
Duplicate URI.
Definition: uri.c:595
char * strdup(const char *src)
Duplicate string.
Definition: string.c:394
const char * efragment
Fragment (with original URI encoding)
Definition: uri.h:87
const char * epath
Path (with original URI encoding)
Definition: uri.h:83
A Uniform Resource Identifier.
Definition: uri.h:65
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322

References uri::efragment, uri::epath, uri::equery, free, memcpy(), NULL, uri::params, uri::path, resolve_path(), strdup(), uri_decode_inplace(), uri_dup(), uri_get(), and uri_is_absolute().

Referenced by churi(), cwuri_fetch_uri(), http_redirect(), imgdownload(), uri_resolve_okx(), and xfer_open_uri().

◆ tftp_uri()

static struct uri* tftp_uri ( struct sockaddr sa_server,
const char *  filename 
)
static

Construct TFTP URI from server address and filename.

Parameters
sa_serverServer address
filenameFilename
Return values
uriURI, or NULL on failure

Definition at line 754 of file uri.c.

755  {
756  struct sockaddr_tcpip *st_server =
757  ( ( struct sockaddr_tcpip * ) sa_server );
758  char buf[ 6 /* "65535" + NUL */ ];
759  char *path;
760  struct uri tmp;
761  struct uri *uri = NULL;
762 
763  /* Initialise TFTP URI */
764  memset ( &tmp, 0, sizeof ( tmp ) );
765  tmp.scheme = "tftp";
766 
767  /* Construct TFTP server address */
768  tmp.host = sock_ntoa ( sa_server );
769  if ( ! tmp.host )
770  goto err_host;
771 
772  /* Construct TFTP server port, if applicable */
773  if ( st_server->st_port ) {
774  snprintf ( buf, sizeof ( buf ), "%d",
775  ntohs ( st_server->st_port ) );
776  tmp.port = buf;
777  }
778 
779  /* Construct TFTP path */
780  if ( asprintf ( &path, "/%s", filename ) < 0 )
781  goto err_path;
782  tmp.path = path;
783  tmp.epath = path;
784 
785  /* Demangle URI */
786  uri = uri_dup ( &tmp );
787  if ( ! uri )
788  goto err_uri;
789 
790  err_uri:
791  free ( path );
792  err_path:
793  err_host:
794  return uri;
795 }
TCP/IP socket address.
Definition: tcpip.h:76
#define ntohs(value)
Definition: byteswap.h:137
unsigned long tmp
Definition: linux_pci.h:65
const char * path
Path (after URI decoding)
Definition: uri.h:81
uint16_t st_port
TCP/IP port.
Definition: tcpip.h:82
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
int asprintf(char **strp, const char *fmt,...)
Write a formatted string to newly allocated memory.
Definition: asprintf.c:42
struct uri * uri_dup(const struct uri *uri)
Duplicate URI.
Definition: uri.c:595
const char * sock_ntoa(struct sockaddr *sa)
Transcribe socket address.
Definition: socket.c:43
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:383
A Uniform Resource Identifier.
Definition: uri.h:65
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
void * memset(void *dest, int character, size_t len) __nonnull

References asprintf(), free, memset(), ntohs, NULL, uri::path, snprintf(), sock_ntoa(), sockaddr_tcpip::st_port, tmp, and uri_dup().

Referenced by pxe_uri().

◆ pxe_uri()

struct uri* pxe_uri ( struct sockaddr sa_server,
const char *  filename 
)

Construct URI from server address and filename.

Parameters
sa_serverServer address
filenameFilename
Return values
uriURI, or NULL on failure

PXE TFTP filenames specified via the DHCP next-server field often contain characters such as ':' or '#' which would confuse the generic URI parser. We provide a mechanism for directly constructing a TFTP URI from the next-server and filename.

Definition at line 809 of file uri.c.

809  {
810  struct uri *uri;
811 
812  /* Fail if filename is empty */
813  if ( ! ( filename && filename[0] ) )
814  return NULL;
815 
816  /* If filename is a hierarchical absolute URI, then use that
817  * URI. (We accept only hierarchical absolute URIs, since PXE
818  * filenames sometimes start with DOS drive letters such as
819  * "C:\", which get misinterpreted as opaque absolute URIs.)
820  */
821  uri = parse_uri ( filename );
822  if ( uri && uri_is_absolute ( uri ) && ( ! uri->opaque ) )
823  return uri;
824  uri_put ( uri );
825 
826  /* Otherwise, construct a TFTP URI directly */
827  return tftp_uri ( sa_server, filename );
828 }
static void uri_put(struct uri *uri)
Decrement URI reference count.
Definition: uri.h:206
static int uri_is_absolute(const struct uri *uri)
URI is an absolute URI.
Definition: uri.h:136
static struct uri * tftp_uri(struct sockaddr *sa_server, const char *filename)
Construct TFTP URI from server address and filename.
Definition: uri.c:754
const char * opaque
Opaque part.
Definition: uri.h:71
A Uniform Resource Identifier.
Definition: uri.h:65
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
struct uri * parse_uri(const char *uri_string)
Parse URI.
Definition: uri.c:297

References NULL, uri::opaque, parse_uri(), tftp_uri(), uri_is_absolute(), and uri_put().

Referenced by efi_pxe_tftp_open(), fetch_next_server_and_filename(), pxe_tftp_open(), and uri_pxe_okx().