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

Detailed Description

Uniform Resource Identifiers.

Definition in file uri.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
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 53 of file uri.c.

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

Referenced by parse_uristring_setting(), and uri_decode_inplace().

                                                                 {
        uint8_t *out = buf;
        unsigned int count = 0;
        char hexbuf[3];
        char *hexbuf_end;
        char c;
        char decoded;
        unsigned int skip;

        /* Copy string, decoding escaped characters as necessary */
        while ( ( c = *(encoded++) ) ) {
                if ( c == '%' ) {
                        snprintf ( hexbuf, sizeof ( hexbuf ), "%s", encoded );
                        decoded = strtoul ( hexbuf, &hexbuf_end, 16 );
                        skip = ( hexbuf_end - hexbuf );
                        encoded += skip;
                        if ( skip )
                                c = decoded;
                }
                if ( count < len )
                        out[count] = c;
                count++;
        }
        return count;
}
static void uri_decode_inplace ( struct uri uri,
unsigned int  field 
) [static]

Decode URI field in-place.

Parameters:
uriURI
fieldURI field index

Definition at line 85 of file uri.c.

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

Referenced by parse_uri().

                                                                       {
        const char *encoded = uri_field ( uri, field );
        char *decoded = ( ( char * ) encoded );
        size_t len;

        /* Do nothing if field is not present */
        if ( ! encoded )
                return;

        /* Decode field in place */
        len = uri_decode ( encoded, decoded, strlen ( encoded ) );

        /* Terminate decoded string */
        decoded[len] = '\0';
}
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 108 of file uri.c.

References isprint(), strchr(), URI_FIELDS, URI_FRAGMENT, URI_HOST, URI_OPAQUE, URI_PASSWORD, URI_PATH, URI_PORT, URI_QUERY, URI_SCHEME, and URI_USER.

Referenced by uri_encode().

                                                                {

        /* Non-printing characters and whitespace should always be
         * escaped, since they cannot sensibly be displayed as part of
         * a coherent URL string.  (This test also catches control
         * characters such as CR and LF, which could affect the
         * operation of line-based protocols such as HTTP.)
         *
         * We should also escape characters which would alter the
         * interpretation of the URL if not escaped, i.e. characters
         * which have significance to the URL parser.  We should not
         * blindly escape all such characters, because this would lead
         * to some very strange-looking URLs (e.g. if we were to
         * always escape '/' as "%2F" even within the URI path).
         *
         * We do not need to be perfect.  Our primary role is as a
         * consumer of URIs rather than a producer; the main situation
         * in which we produce a URI string is for display to a human
         * user, who can probably tolerate some variance from the
         * formal specification.  The only situation in which we
         * currently produce a URI string to be consumed by a computer
         * is when constructing an HTTP request URI, which contains
         * only the path and query fields.
         *
         * We can therefore sacrifice some correctness for the sake of
         * code size.  For example, colons within the URI host should
         * be escaped unless they form part of an IPv6 literal
         * address; doing this correctly would require the URI
         * formatter to be aware of whether or not the URI host
         * contained an IPv4 address, an IPv6 address, or a host name.
         * We choose to simplify and never escape colons within the
         * URI host field: in the event of a pathological hostname
         * containing colons, this could potentially produce a URI
         * string which could not be reparsed.
         *
         * After excluding non-printing characters, whitespace, and
         * '%', the full set of characters with significance to the
         * URL parser is "/#:@?".  We choose for each URI field which
         * of these require escaping in our use cases.
         *
         * For the scheme field (equivalently, if field is zero), we
         * escape anything that has significance not just for our URI
         * parser but for any other URI parsers (e.g. HTTP query
         * string parsers, which care about '=' and '&').
         */
        static const char *escaped[URI_FIELDS] = {
                /* Scheme or default: escape everything */
                [URI_SCHEME]    = "/#:@?=&",
                /* Opaque part: escape characters which would affect
                 * the reparsing of the URI, allowing everything else
                 * (e.g. ':', which will appear in iSCSI URIs).
                 */
                [URI_OPAQUE]    = "#",
                /* User name: escape everything */
                [URI_USER]      = "/#:@?",
                /* Password: escape everything */
                [URI_PASSWORD]  = "/#:@?",
                /* Host name: escape everything except ':', which may
                 * appear as part of an IPv6 literal address.
                 */
                [URI_HOST]      = "/#@?",
                /* Port number: escape everything */
                [URI_PORT]      = "/#:@?",
                /* Path: escape everything except '/', which usually
                 * appears within paths.
                 */
                [URI_PATH]      = "#:@?",
                /* Query: escape everything except '/', which
                 * sometimes appears within queries.
                 */
                [URI_QUERY]     = "#:@?",
                /* Fragment: escape everything */
                [URI_FRAGMENT]  = "/#:@?",
        };

        return ( /* Always escape non-printing characters and whitespace */
                 ( ! isprint ( c ) ) || ( c == ' ' ) ||
                 /* Always escape '%' */
                 ( c == '%' ) ||
                 /* Escape field-specific characters */
                 strchr ( escaped[field], c ) );
}
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.

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

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

                                             {
        const uint8_t *raw_bytes = ( ( const uint8_t * ) raw );
        ssize_t remaining = len;
        size_t used;
        char c;

        /* Ensure encoded string is NUL-terminated even if empty */
        if ( len > 0 )
                buf[0] = '\0';

        /* Copy string, escaping as necessary */
        while ( raw_len-- ) {
                c = *(raw_bytes++);
                if ( uri_character_escaped ( c, field ) ) {
                        used = ssnprintf ( buf, remaining, "%%%02X", c );
                } else {
                        used = ssnprintf ( buf, remaining, "%c", c );
                }
                buf += used;
                remaining -= used;
        }

        return ( len - remaining );
}
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.

References strlen(), and uri_encode().

Referenced by format_uri(), and http_params().

                                                    {

        return uri_encode ( field, string, strlen ( string ), buf, len );
}
static void uri_dump ( const struct uri uri) [static]

Dump URI for debugging.

Parameters:
uriURI

Definition at line 247 of file uri.c.

References DBGC, uri::fragment, uri::host, parameters::name, uri::opaque, uri::params, uri::password, uri::path, uri::port, uri::query, uri::scheme, and uri::user.

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

                                               {

        if ( ! uri )
                return;
        if ( uri->scheme )
                DBGC ( uri, " scheme \"%s\"", uri->scheme );
        if ( uri->opaque )
                DBGC ( uri, " opaque \"%s\"", uri->opaque );
        if ( uri->user )
                DBGC ( uri, " user \"%s\"", uri->user );
        if ( uri->password )
                DBGC ( uri, " password \"%s\"", uri->password );
        if ( uri->host )
                DBGC ( uri, " host \"%s\"", uri->host );
        if ( uri->port )
                DBGC ( uri, " port \"%s\"", uri->port );
        if ( uri->path )
                DBGC ( uri, " path \"%s\"", uri->path );
        if ( uri->query )
                DBGC ( uri, " query \"%s\"", uri->query );
        if ( uri->fragment )
                DBGC ( uri, " fragment \"%s\"", uri->fragment );
        if ( uri->params )
                DBGC ( uri, " params \"%s\"", uri->params->name );
}
static void uri_free ( struct refcnt refcnt) [static]

Free URI.

Parameters:
refcntReference count

Definition at line 278 of file uri.c.

References container_of, free, and uri::params.

Referenced by parse_uri(), and uri_dup().

                                               {
        struct uri *uri = container_of ( refcnt, struct uri, refcnt );

        params_put ( uri->params );
        free ( uri );
}
struct uri* parse_uri ( const char *  uri_string) [read]

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 295 of file uri.c.

References DBGC, done, find_parameters(), uri::fragment, uri::host, memcpy(), memmove(), NULL, uri::opaque, uri::params, params, uri::password, uri::path, uri::port, uri::query, raw, raw_len, ref_init, uri::refcnt, uri::scheme, strchr(), strlen(), strncmp(), strrchr(), strstr(), uri_decode_inplace(), uri_dump(), URI_FIELDS, uri_free(), uri::user, and zalloc().

Referenced by 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().

                                                  {
        struct uri *uri;
        struct parameters *params;
        char *raw;
        char *tmp;
        char *path;
        char *authority;
        size_t raw_len;
        unsigned int field;

        /* Allocate space for URI struct and a copy of the string */
        raw_len = ( strlen ( uri_string ) + 1 /* NUL */ );
        uri = zalloc ( sizeof ( *uri ) + raw_len );
        if ( ! uri )
                return NULL;
        ref_init ( &uri->refcnt, uri_free );
        raw = ( ( ( void * ) uri ) + sizeof ( *uri ) );

        /* Copy in the raw string */
        memcpy ( raw, uri_string, raw_len );

        /* Identify the parameter list, if present */
        if ( ( tmp = strstr ( raw, "##params" ) ) ) {
                *tmp = '\0';
                tmp += 8 /* "##params" */;
                params = find_parameters ( *tmp ? ( tmp + 1 ) : NULL );
                if ( params ) {
                        uri->params = claim_parameters ( params );
                } else {
                        /* Ignore non-existent submission blocks */
                }
        }

        /* Chop off the fragment, if it exists */
        if ( ( tmp = strchr ( raw, '#' ) ) ) {
                *(tmp++) = '\0';
                uri->fragment = tmp;
        }

        /* Identify absolute/relative URI */
        if ( ( tmp = strchr ( raw, ':' ) ) ) {
                /* Absolute URI: identify hierarchical/opaque */
                uri->scheme = raw;
                *(tmp++) = '\0';
                if ( *tmp == '/' ) {
                        /* Absolute URI with hierarchical part */
                        path = tmp;
                } else {
                        /* Absolute URI with opaque part */
                        uri->opaque = tmp;
                        path = NULL;
                }
        } else {
                /* Relative URI */
                path = raw;
        }

        /* If we don't have a path (i.e. we have an absolute URI with
         * an opaque portion, we're already finished processing
         */
        if ( ! path )
                goto done;

        /* Chop off the query, if it exists */
        if ( ( tmp = strchr ( path, '?' ) ) ) {
                *(tmp++) = '\0';
                uri->query = tmp;
        }

        /* If we have no path remaining, then we're already finished
         * processing.
         */
        if ( ! path[0] )
                goto done;

        /* Identify net/absolute/relative path */
        if ( uri->scheme && ( strncmp ( path, "//", 2 ) == 0 ) ) {
                /* Net path.  If this is terminated by the first '/'
                 * of an absolute path, then we have no space for a
                 * terminator after the authority field, so shuffle
                 * the authority down by one byte, overwriting one of
                 * the two slashes.
                 */
                authority = ( path + 2 );
                if ( ( tmp = strchr ( authority, '/' ) ) ) {
                        /* Shuffle down */
                        uri->path = tmp;
                        memmove ( ( authority - 1 ), authority,
                                  ( tmp - authority ) );
                        authority--;
                        *(--tmp) = '\0';
                }
        } else {
                /* Absolute/relative path */
                uri->path = path;
                authority = NULL;
        }

        /* If we don't have an authority (i.e. we have a non-net
         * path), we're already finished processing
         */
        if ( ! authority )
                goto done;

        /* Split authority into user[:password] and host[:port] portions */
        if ( ( tmp = strchr ( authority, '@' ) ) ) {
                /* Has user[:password] */
                *(tmp++) = '\0';
                uri->host = tmp;
                uri->user = authority;
                if ( ( tmp = strchr ( authority, ':' ) ) ) {
                        /* Has password */
                        *(tmp++) = '\0';
                        uri->password = tmp;
                }
        } else {
                /* No user:password */
                uri->host = authority;
        }

        /* Split host into host[:port] */
        if ( ( uri->host[ strlen ( uri->host ) - 1 ] != ']' ) &&
             ( tmp = strrchr ( uri->host, ':' ) ) ) {
                *(tmp++) = '\0';
                uri->port = tmp;
        }

 done:
        /* Decode fields in-place */
        for ( field = 0 ; field < URI_FIELDS ; field++ )
                uri_decode_inplace ( uri, field );

        DBGC ( uri, "URI parsed \"%s\" to", uri_string );
        uri_dump ( uri );
        DBGC ( uri, "\n" );

        return uri;
}
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 441 of file uri.c.

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().

                                                                           {

        if ( ( ! uri ) || ( ! uri->port ) )
                return default_port;

        return ( strtoul ( uri->port, NULL, 0 ) );
}
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 457 of file uri.c.

References DBGC, uri::host, NULL, prefix, ssnprintf(), uri_dump(), uri_encode_string(), uri_field, URI_FIELDS, URI_FRAGMENT, URI_HOST, URI_PASSWORD, URI_PORT, URI_QUERY, URI_SCHEME, and uri::user.

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

                                                                   {
        static const char prefixes[URI_FIELDS] = {
                [URI_PASSWORD] = ':',
                [URI_PORT] = ':',
                [URI_QUERY] = '?',
                [URI_FRAGMENT] = '#',
        };
        char prefix;
        size_t used = 0;
        unsigned int field;

        /* Ensure buffer is NUL-terminated */
        if ( len )
                buf[0] = '\0';

        /* Special-case NULL URI */
        if ( ! uri )
                return 0;

        /* Generate fields */
        for ( field = 0 ; field < URI_FIELDS ; field++ ) {

                /* Skip non-existent fields */
                if ( ! uri_field ( uri, field ) )
                        continue;

                /* Prefix this field, if applicable */
                prefix = prefixes[field];
                if ( ( field == URI_HOST ) && ( uri->user != NULL ) )
                        prefix = '@';
                if ( prefix ) {
                        used += ssnprintf ( ( buf + used ), ( len - used ),
                                            "%c", prefix );
                }

                /* Encode this field */
                used += uri_encode_string ( field, uri_field ( uri, field ),
                                            ( buf + used ), ( len - used ) );

                /* Suffix this field, if applicable */
                if ( field == URI_SCHEME ) {
                        used += ssnprintf ( ( buf + used ), ( len - used ),
                                            ":%s", ( uri->host ? "//" : "" ) );
                }
        }

        if ( len ) {
                DBGC ( uri, "URI formatted" );
                uri_dump ( uri );
                DBGC ( uri, " to \"%s%s\"\n", buf,
                       ( ( used > len ) ? "<TRUNCATED>" : "" ) );
        }

        return used;
}
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 522 of file uri.c.

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

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

                                                  {
        size_t len;
        char *string;

        len = ( format_uri ( uri, NULL, 0 ) + 1 /* NUL */ );
        string = malloc ( len );
        if ( string )
                format_uri ( uri, string, len );
        return string;
}
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 540 of file uri.c.

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

Referenced by uri_dup().

                                                                          {
        size_t len = sizeof ( *dest );
        char *out = ( ( void * ) dest + len );
        unsigned int field;
        size_t field_len;

        /* Copy existent fields */
        for ( field = 0 ; field < URI_FIELDS ; field++ ) {

                /* Skip non-existent fields */
                if ( ! uri_field ( src, field ) )
                        continue;

                /* Calculate field length */
                field_len = ( strlen ( uri_field ( src, field ) )
                              + 1 /* NUL */ );
                len += field_len;

                /* Copy field, if applicable */
                if ( dest ) {
                        memcpy ( out, uri_field ( src, field ), field_len );
                        uri_field ( dest, field ) = out;
                        out += field_len;
                }
        }
        return len;
}
struct uri* uri_dup ( const struct uri uri) [read]

Duplicate URI.

Parameters:
uriURI
Return values:
uriDuplicate URI

Creates a modifiable copy of a URI.

Definition at line 576 of file uri.c.

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().

                                               {
        struct uri *dup;
        size_t len;

        /* Allocate new URI */
        len = uri_copy_fields ( uri, NULL );
        dup = zalloc ( len );
        if ( ! dup )
                return NULL;
        ref_init ( &dup->refcnt, uri_free );

        /* Copy fields */
        uri_copy_fields ( uri, dup );

        /* Copy parameters */
        dup->params = params_get ( uri->params );

        DBGC ( uri, "URI duplicated" );
        uri_dump ( uri );
        DBGC ( uri, "\n" );

        return dup;
}
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 614 of file uri.c.

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

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

                                                  {
        char *base_copy;
        char *base_tmp;
        char *resolved;

        /* If relative path is absolute, just re-use it */
        if ( relative_path[0] == '/' )
                return strdup ( relative_path );

        /* Create modifiable copy of path for dirname() */
        base_copy = strdup ( base_path );
        if ( ! base_copy )
                return NULL;

        /* Strip filename portion of base path */
        base_tmp = dirname ( base_copy );

        /* Process "./" and "../" elements */
        while ( *relative_path == '.' ) {
                relative_path++;
                if ( *relative_path == 0 ) {
                        /* Do nothing */
                } else if ( *relative_path == '/' ) {
                        relative_path++;
                } else if ( *relative_path == '.' ) {
                        relative_path++;
                        if ( *relative_path == 0 ) {
                                base_tmp = dirname ( base_tmp );
                        } else if ( *relative_path == '/' ) {
                                base_tmp = dirname ( base_tmp );
                                relative_path++;
                        } else {
                                relative_path -= 2;
                                break;
                        }
                } else {
                        relative_path--;
                        break;
                }
        }

        /* Create and return new path */
        if ( asprintf ( &resolved, "%s%s%s", base_tmp,
                        ( ( base_tmp[ strlen ( base_tmp ) - 1 ] == '/' ) ?
                          "" : "/" ), relative_path ) < 0 )
                resolved = NULL;
        free ( base_copy );
        return resolved;
}
struct uri* resolve_uri ( const struct uri base_uri,
struct uri relative_uri 
) [read]

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 676 of file uri.c.

References uri::fragment, free, memcpy(), NULL, uri::params, uri::path, uri::query, resolve_path(), uri_dup(), uri_get(), and uri_is_absolute().

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

                                                      {
        struct uri tmp_uri;
        char *tmp_path = NULL;
        struct uri *new_uri;

        /* If relative URI is absolute, just re-use it */
        if ( uri_is_absolute ( relative_uri ) || ( ! base_uri ) )
                return uri_get ( relative_uri );

        /* Mangle URI */
        memcpy ( &tmp_uri, base_uri, sizeof ( tmp_uri ) );
        if ( relative_uri->path ) {
                tmp_path = resolve_path ( ( base_uri->path ?
                                            base_uri->path : "/" ),
                                          relative_uri->path );
                tmp_uri.path = tmp_path;
                tmp_uri.query = relative_uri->query;
                tmp_uri.fragment = relative_uri->fragment;
                tmp_uri.params = relative_uri->params;
        } else if ( relative_uri->query ) {
                tmp_uri.query = relative_uri->query;
                tmp_uri.fragment = relative_uri->fragment;
                tmp_uri.params = relative_uri->params;
        } else if ( relative_uri->fragment ) {
                tmp_uri.fragment = relative_uri->fragment;
                tmp_uri.params = relative_uri->params;
        } else if ( relative_uri->params ) {
                tmp_uri.params = relative_uri->params;
        }

        /* Create demangled URI */
        new_uri = uri_dup ( &tmp_uri );
        free ( tmp_path );
        return new_uri;
}
static struct uri* tftp_uri ( struct sockaddr sa_server,
const char *  filename 
) [static, read]

Construct TFTP URI from server address and filename.

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

Definition at line 720 of file uri.c.

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

Referenced by pxe_uri().

                                                      {
        struct sockaddr_tcpip *st_server =
                ( ( struct sockaddr_tcpip * ) sa_server );
        char buf[ 6 /* "65535" + NUL */ ];
        char *path;
        struct uri tmp;
        struct uri *uri = NULL;

        /* Initialise TFTP URI */
        memset ( &tmp, 0, sizeof ( tmp ) );
        tmp.scheme = "tftp";

        /* Construct TFTP server address */
        tmp.host = sock_ntoa ( sa_server );
        if ( ! tmp.host )
                goto err_host;

        /* Construct TFTP server port, if applicable */
        if ( st_server->st_port ) {
                snprintf ( buf, sizeof ( buf ), "%d",
                           ntohs ( st_server->st_port ) );
                tmp.port = buf;
        }

        /* Construct TFTP path */
        if ( asprintf ( &path, "/%s", filename ) < 0 )
                goto err_path;
        tmp.path = path;

        /* Demangle URI */
        uri = uri_dup ( &tmp );
        if ( ! uri )
                goto err_uri;

 err_uri:
        free ( path );
 err_path:
 err_host:
        return uri;
}
struct uri* pxe_uri ( struct sockaddr sa_server,
const char *  filename 
) [read]

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 774 of file uri.c.

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().

                                                                          {
        struct uri *uri;

        /* Fail if filename is empty */
        if ( ! ( filename && filename[0] ) )
                return NULL;

        /* If filename is a hierarchical absolute URI, then use that
         * URI.  (We accept only hierarchical absolute URIs, since PXE
         * filenames sometimes start with DOS drive letters such as
         * "C:\", which get misinterpreted as opaque absolute URIs.)
         */
        uri = parse_uri ( filename );
        if ( uri && uri_is_absolute ( uri ) && ( ! uri->opaque ) )
                return uri;
        uri_put ( uri );

        /* Otherwise, construct a TFTP URI directly */
        return tftp_uri ( sa_server, filename );
}