#include "string.h" #include "resolv.h" #include "etherboot.h" /* for arptable */ #include "url.h" /* * Parse a URL and deduce a struct protocol *, a struct sockaddr_in * and a char *filename. * * We accept URLs of the form * * [protocol://[host][:port]/]path/to/file * * Returns 1 for success, 0 for failure (e.g. unknown protocol). * */ int parse_url ( char *url, struct protocol **proto, struct sockaddr_in *server, char **filename ) { char *p; char *protocol = NULL; char *host = NULL; char *port = NULL; int rc = 0; DBG ( "URL parsing \"%s\"\n", url ); /* If no protocol is present, the whole URL will be a filename */ *filename = url; /* Search for a protocol delimiter. If found, parse out the * host and port parts of the URL, inserting NULs to terminate * the different sections. */ for ( p = url ; *p ; p++ ) { if ( memcmp ( p, "://", 3 ) != 0 ) continue; /* URL has an explicit protocol */ *p = '\0'; p += 3; protocol = url; host = p; /* Search for port and file delimiters */ for ( ; *p ; p++ ) { if ( *p == ':' ) { *p = '\0'; port = p + 1; continue; } if ( *p == '/' ) { *(p++) = '\0'; break; } } *filename = p; break; } DBG ( "URL protocol \"%s\" host \"%s\" port \"%s\" file \"%s\"\n", protocol ? protocol : "(default)", host ? host : "(default)", port ? port : "(default)", *filename ); /* Identify the protocol */ *proto = identify_protocol ( protocol ); if ( ! *proto ) { DBG ( "URL unknown protocol \"%s\"\n", protocol ? protocol : "(default)" ); goto out; } /* Identify the host */ server->sin_addr = arptable[ARP_SERVER].ipaddr; if ( host && host[0] ) { if ( ! resolv ( &server->sin_addr, host ) ) { DBG ( "URL unknown host \"%s\"\n", host ); goto out; } } /* Identify the port */ server->sin_port = (*proto)->default_port; if ( port && port[0] ) { server->sin_port = strtoul ( port, NULL, 10 ); } rc = 1; out: /* Fill back in the original URL */ if ( protocol ) { (*filename)[-1] = '/'; if ( port ) port[-1] = ':'; host[-3] = ':'; } return rc; }