| 
				
			 | 
			
			
				
				@@ -1,42 +1,51 @@ 
			 | 
		
		
	
		
			
			| 
				1
			 | 
			
				1
			 | 
			
			
				
				 #include "string.h" 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				2
			 | 
			
			
				
				+#include "resolv.h" 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				3
			 | 
			
			
				
				+#include "etherboot.h" /* for arptable */ 
			 | 
		
		
	
		
			
			| 
				2
			 | 
			
				4
			 | 
			
			
				
				 #include "url.h" 
			 | 
		
		
	
		
			
			| 
				3
			 | 
			
				5
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				4
			 | 
			
				6
			 | 
			
			
				
				 /* 
			 | 
		
		
	
		
			
			| 
				5
			 | 
			
				
			 | 
			
			
				
				- * Parse a URL string into its constituent parts. 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				7
			 | 
			
			
				
				+ * Parse a URL and deduce a struct protocol *, a struct sockaddr_in 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				8
			 | 
			
			
				
				+ * and a char *filename. 
			 | 
		
		
	
		
			
			| 
				6
			 | 
			
				9
			 | 
			
			
				
				  * 
			 | 
		
		
	
		
			
			| 
				7
			 | 
			
				10
			 | 
			
			
				
				  * We accept URLs of the form 
			 | 
		
		
	
		
			
			| 
				8
			 | 
			
				11
			 | 
			
			
				
				  * 
			 | 
		
		
	
		
			
			| 
				9
			 | 
			
				12
			 | 
			
			
				
				  *   [protocol://[host][:port]/]path/to/file 
			 | 
		
		
	
		
			
			| 
				10
			 | 
			
				13
			 | 
			
			
				
				  * 
			 | 
		
		
	
		
			
			| 
				11
			 | 
			
				
			 | 
			
			
				
				- * The URL string will be modified by having NULs inserted after 
			 | 
		
		
	
		
			
			| 
				12
			 | 
			
				
			 | 
			
			
				
				- * "protocol", "host" and "port".  The original URL can be 
			 | 
		
		
	
		
			
			| 
				13
			 | 
			
				
			 | 
			
			
				
				- * reconstructed by calling unparse_url. 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				14
			 | 
			
			
				
				+ * Returns 1 for success, 0 for failure (e.g. unknown protocol). 
			 | 
		
		
	
		
			
			| 
				14
			 | 
			
				15
			 | 
			
			
				
				  * 
			 | 
		
		
	
		
			
			| 
				15
			 | 
			
				16
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				16
			 | 
			
				
			 | 
			
			
				
				-void parse_url ( struct url_info *info, char *url ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				17
			 | 
			
			
				
				+int parse_url ( char *url, struct protocol **proto, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				18
			 | 
			
			
				
				+		struct sockaddr_in *server, char **filename ) { 
			 | 
		
		
	
		
			
			| 
				17
			 | 
			
				19
			 | 
			
			
				
				 	char *p; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				20
			 | 
			
			
				
				+	char *protocol = NULL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				21
			 | 
			
			
				
				+	char *host = NULL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				22
			 | 
			
			
				
				+	char *port = NULL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				23
			 | 
			
			
				
				+	int rc = 0; 
			 | 
		
		
	
		
			
			| 
				18
			 | 
			
				24
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				19
			 | 
			
				25
			 | 
			
			
				
				 	DBG ( "URL parsing \"%s\"\n", url ); 
			 | 
		
		
	
		
			
			| 
				20
			 | 
			
				26
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				21
			 | 
			
				
			 | 
			
			
				
				-	/* Zero the structure */ 
			 | 
		
		
	
		
			
			| 
				22
			 | 
			
				
			 | 
			
			
				
				-	memset ( info, 0, sizeof ( *info ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				27
			 | 
			
			
				
				+	/* If no protocol is present, the whole URL will be a filename */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				28
			 | 
			
			
				
				+	*filename = url; 
			 | 
		
		
	
		
			
			| 
				23
			 | 
			
				29
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				24
			 | 
			
				
			 | 
			
			
				
				-	/* Search for a protocol delimiter */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				30
			 | 
			
			
				
				+	/* Search for a protocol delimiter.  If found, parse out the 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				31
			 | 
			
			
				
				+	 * host and port parts of the URL, inserting NULs to terminate 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				32
			 | 
			
			
				
				+	 * the different sections. 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				33
			 | 
			
			
				
				+	 */ 
			 | 
		
		
	
		
			
			| 
				25
			 | 
			
				34
			 | 
			
			
				
				 	for ( p = url ; *p ; p++ ) { 
			 | 
		
		
	
		
			
			| 
				26
			 | 
			
				35
			 | 
			
			
				
				 		if ( memcmp ( p, "://", 3 ) != 0 ) 
			 | 
		
		
	
		
			
			| 
				27
			 | 
			
				36
			 | 
			
			
				
				 			continue; 
			 | 
		
		
	
		
			
			| 
				28
			 | 
			
				37
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				29
			 | 
			
				38
			 | 
			
			
				
				 		/* URL has an explicit protocol */ 
			 | 
		
		
	
		
			
			| 
				30
			 | 
			
				
			 | 
			
			
				
				-		info->protocol = url; 
			 | 
		
		
	
		
			
			| 
				31
			 | 
			
				39
			 | 
			
			
				
				 		*p = '\0'; 
			 | 
		
		
	
		
			
			| 
				32
			 | 
			
				40
			 | 
			
			
				
				 		p += 3; 
			 | 
		
		
	
		
			
			| 
				33
			 | 
			
				
			 | 
			
			
				
				-		info->host = p; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				41
			 | 
			
			
				
				+		protocol = url; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				42
			 | 
			
			
				
				+		host = p; 
			 | 
		
		
	
		
			
			| 
				34
			 | 
			
				43
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				35
			 | 
			
				
			 | 
			
			
				
				-		/* Search for port or file delimiter */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				44
			 | 
			
			
				
				+		/* Search for port and file delimiters */ 
			 | 
		
		
	
		
			
			| 
				36
			 | 
			
				45
			 | 
			
			
				
				 		for ( ; *p ; p++ ) { 
			 | 
		
		
	
		
			
			| 
				37
			 | 
			
				46
			 | 
			
			
				
				 			if ( *p == ':' ) { 
			 | 
		
		
	
		
			
			| 
				38
			 | 
			
				47
			 | 
			
			
				
				 				*p = '\0'; 
			 | 
		
		
	
		
			
			| 
				39
			 | 
			
				
			 | 
			
			
				
				-				info->port = p + 1; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				48
			 | 
			
			
				
				+				port = p + 1; 
			 | 
		
		
	
		
			
			| 
				40
			 | 
			
				49
			 | 
			
			
				
				 				continue; 
			 | 
		
		
	
		
			
			| 
				41
			 | 
			
				50
			 | 
			
			
				
				 			} 
			 | 
		
		
	
		
			
			| 
				42
			 | 
			
				51
			 | 
			
			
				
				 			if ( *p == '/' ) { 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -44,35 +53,46 @@ void parse_url ( struct url_info *info, char *url ) { 
			 | 
		
		
	
		
			
			| 
				44
			 | 
			
				53
			 | 
			
			
				
				 				break; 
			 | 
		
		
	
		
			
			| 
				45
			 | 
			
				54
			 | 
			
			
				
				 			} 
			 | 
		
		
	
		
			
			| 
				46
			 | 
			
				55
			 | 
			
			
				
				 		} 
			 | 
		
		
	
		
			
			| 
				47
			 | 
			
				
			 | 
			
			
				
				-		info->file = p; 
			 | 
		
		
	
		
			
			| 
				48
			 | 
			
				
			 | 
			
			
				
				-		DBG ( "URL protocol \"%s\" host \"%s\" port \"%s\" " 
			 | 
		
		
	
		
			
			| 
				49
			 | 
			
				
			 | 
			
			
				
				-		      "file \"%s\"\n", info->protocol, info->host, 
			 | 
		
		
	
		
			
			| 
				50
			 | 
			
				
			 | 
			
			
				
				-		      info->port ? info->port : "(NONE)", info->file ); 
			 | 
		
		
	
		
			
			| 
				51
			 | 
			
				
			 | 
			
			
				
				-		return; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				56
			 | 
			
			
				
				+		*filename = p; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				57
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				58
			 | 
			
			
				
				+		break; 
			 | 
		
		
	
		
			
			| 
				52
			 | 
			
				59
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				60
			 | 
			
			
				
				+	DBG ( "URL protocol \"%s\" host \"%s\" port \"%s\" file \"%s\"\n", 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				61
			 | 
			
			
				
				+	      protocol ? protocol : "(default)", host ? host : "(default)", 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				62
			 | 
			
			
				
				+	      port ? port : "(default)", *filename ); 
			 | 
		
		
	
		
			
			| 
				53
			 | 
			
				63
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				54
			 | 
			
				
			 | 
			
			
				
				-	/* URL has no explicit protocol; is just a filename */ 
			 | 
		
		
	
		
			
			| 
				55
			 | 
			
				
			 | 
			
			
				
				-	info->file = url; 
			 | 
		
		
	
		
			
			| 
				56
			 | 
			
				
			 | 
			
			
				
				-	DBG ( "URL file \"%s\"\n", info->file ); 
			 | 
		
		
	
		
			
			| 
				57
			 | 
			
				
			 | 
			
			
				
				-} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				64
			 | 
			
			
				
				+	/* Identify the protocol */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				65
			 | 
			
			
				
				+	*proto = identify_protocol ( protocol ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				66
			 | 
			
			
				
				+	if ( ! *proto ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				67
			 | 
			
			
				
				+		DBG ( "URL unknown protocol \"%s\"\n", 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				68
			 | 
			
			
				
				+		      protocol ? protocol : "(default)" ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				69
			 | 
			
			
				
				+		goto out; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				70
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				58
			 | 
			
				71
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				59
			 | 
			
				
			 | 
			
			
				
				-/* 
			 | 
		
		
	
		
			
			| 
				60
			 | 
			
				
			 | 
			
			
				
				- * Restore a parsed URL to its original pristine form. 
			 | 
		
		
	
		
			
			| 
				61
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				62
			 | 
			
				
			 | 
			
			
				
				- */ 
			 | 
		
		
	
		
			
			| 
				63
			 | 
			
				
			 | 
			
			
				
				-char * unparse_url ( struct url_info *info ) { 
			 | 
		
		
	
		
			
			| 
				64
			 | 
			
				
			 | 
			
			
				
				-	if ( info->protocol ) { 
			 | 
		
		
	
		
			
			| 
				65
			 | 
			
				
			 | 
			
			
				
				-		/* URL had a protocol: fill in the deleted separators */ 
			 | 
		
		
	
		
			
			| 
				66
			 | 
			
				
			 | 
			
			
				
				-		info->file[-1] = '/'; 
			 | 
		
		
	
		
			
			| 
				67
			 | 
			
				
			 | 
			
			
				
				-		if ( info->port ) { 
			 | 
		
		
	
		
			
			| 
				68
			 | 
			
				
			 | 
			
			
				
				-			info->port[-1] = ':'; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				72
			 | 
			
			
				
				+	/* Identify the host */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				73
			 | 
			
			
				
				+	server->sin_addr = arptable[ARP_SERVER].ipaddr; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				74
			 | 
			
			
				
				+	if ( host && host[0] ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				75
			 | 
			
			
				
				+		if ( ! resolv ( &server->sin_addr, host ) ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				76
			 | 
			
			
				
				+			DBG ( "URL unknown host \"%s\"\n", host ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				77
			 | 
			
			
				
				+			goto out; 
			 | 
		
		
	
		
			
			| 
				69
			 | 
			
				78
			 | 
			
			
				
				 		} 
			 | 
		
		
	
		
			
			| 
				70
			 | 
			
				
			 | 
			
			
				
				-		info->host[-3] = ':'; 
			 | 
		
		
	
		
			
			| 
				71
			 | 
			
				
			 | 
			
			
				
				-		DBG ( "URL reconstructed \"%s\"\n", info->protocol ); 
			 | 
		
		
	
		
			
			| 
				72
			 | 
			
				
			 | 
			
			
				
				-		return info->protocol; 
			 | 
		
		
	
		
			
			| 
				73
			 | 
			
				
			 | 
			
			
				
				-	} else { 
			 | 
		
		
	
		
			
			| 
				74
			 | 
			
				
			 | 
			
			
				
				-		/* URL had no protocol; was just a filename */ 
			 | 
		
		
	
		
			
			| 
				75
			 | 
			
				
			 | 
			
			
				
				-		DBG ( "URL reconstructed \"%s\"\n", info->file ); 
			 | 
		
		
	
		
			
			| 
				76
			 | 
			
				
			 | 
			
			
				
				-		return info->file; 
			 | 
		
		
	
		
			
			| 
				77
			 | 
			
				79
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				80
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				81
			 | 
			
			
				
				+	/* Identify the port */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				82
			 | 
			
			
				
				+	server->sin_port = (*proto)->default_port; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				83
			 | 
			
			
				
				+	if ( port && port[0] ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				84
			 | 
			
			
				
				+		server->sin_port = strtoul ( port, NULL, 10 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				85
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				86
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				87
			 | 
			
			
				
				+	rc = 1; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				88
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				89
			 | 
			
			
				
				+ out: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				90
			 | 
			
			
				
				+	/* Fill back in the original URL */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				91
			 | 
			
			
				
				+	if ( protocol ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				92
			 | 
			
			
				
				+		(*filename)[-1] = '/'; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				93
			 | 
			
			
				
				+		if ( port ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				94
			 | 
			
			
				
				+			port[-1] = ':'; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				95
			 | 
			
			
				
				+		host[-3] = ':'; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				96
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				97
			 | 
			
			
				
				+	return rc; 
			 | 
		
		
	
		
			
			| 
				78
			 | 
			
				98
			 | 
			
			
				
				 } 
			 |