| 
				
			 | 
			
			
				
				@@ -190,7 +190,7 @@ static void del_ipv6_miniroute ( struct ipv6_miniroute *miniroute ) { 
			 | 
		
		
	
		
			
			| 
				190
			 | 
			
				190
			 | 
			
			
				
				  * @ret miniroute	Routing table entry to use, or NULL if no route 
			 | 
		
		
	
		
			
			| 
				191
			 | 
			
				191
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				192
			 | 
			
				192
			 | 
			
			
				
				 static struct ipv6_miniroute * ipv6_route ( unsigned int scope_id, 
			 | 
		
		
	
		
			
			| 
				193
			 | 
			
				
			 | 
			
			
				
				-					   struct in6_addr **dest ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				193
			 | 
			
			
				
				+					    struct in6_addr **dest ) { 
			 | 
		
		
	
		
			
			| 
				194
			 | 
			
				194
			 | 
			
			
				
				 	struct ipv6_miniroute *miniroute; 
			 | 
		
		
	
		
			
			| 
				195
			 | 
			
				195
			 | 
			
			
				
				 	int local; 
			 | 
		
		
	
		
			
			| 
				196
			 | 
			
				196
			 | 
			
			
				
				  
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -749,6 +749,96 @@ static const char * ipv6_ntoa ( const void *net_addr ) { 
			 | 
		
		
	
		
			
			| 
				749
			 | 
			
				749
			 | 
			
			
				
				 	return inet6_ntoa ( net_addr ); 
			 | 
		
		
	
		
			
			| 
				750
			 | 
			
				750
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				751
			 | 
			
				751
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				752
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				753
			 | 
			
			
				
				+ * Transcribe IPv6 socket address 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				754
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				755
			 | 
			
			
				
				+ * @v sa		Socket address 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				756
			 | 
			
			
				
				+ * @ret string		Socket address in standard notation 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				757
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				758
			 | 
			
			
				
				+static const char * ipv6_sock_ntoa ( struct sockaddr *sa ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				759
			 | 
			
			
				
				+	static char buf[ 39 /* "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx" */ + 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				760
			 | 
			
			
				
				+			 1 /* "%" */ + NETDEV_NAME_LEN + 1 /* NUL */ ]; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				761
			 | 
			
			
				
				+	struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) sa ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				762
			 | 
			
			
				
				+	struct in6_addr *in = &sin6->sin6_addr; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				763
			 | 
			
			
				
				+	struct net_device *netdev; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				764
			 | 
			
			
				
				+	const char *netdev_name; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				765
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				766
			 | 
			
			
				
				+	/* Identify network device, if applicable */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				767
			 | 
			
			
				
				+	if ( IN6_IS_ADDR_LINKLOCAL ( in ) ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				768
			 | 
			
			
				
				+		netdev = find_netdev_by_index ( sin6->sin6_scope_id ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				769
			 | 
			
			
				
				+		netdev_name = ( netdev ? netdev->name : "UNKNOWN" ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				770
			 | 
			
			
				
				+	} else { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				771
			 | 
			
			
				
				+		netdev_name = NULL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				772
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				773
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				774
			 | 
			
			
				
				+	/* Format socket address */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				775
			 | 
			
			
				
				+	snprintf ( buf, sizeof ( buf ), "%s%s%s", inet6_ntoa ( in ), 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				776
			 | 
			
			
				
				+		   ( netdev_name ? "%" : "" ), 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				777
			 | 
			
			
				
				+		   ( netdev_name ? netdev_name : "" ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				778
			 | 
			
			
				
				+	return buf; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				779
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				780
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				781
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				782
			 | 
			
			
				
				+ * Parse IPv6 socket address 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				783
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				784
			 | 
			
			
				
				+ * @v string		Socket address string 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				785
			 | 
			
			
				
				+ * @v sa		Socket address to fill in 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				786
			 | 
			
			
				
				+ * @ret rc		Return status code 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				787
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				788
			 | 
			
			
				
				+static int ipv6_sock_aton ( const char *string, struct sockaddr *sa ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				789
			 | 
			
			
				
				+	struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) sa ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				790
			 | 
			
			
				
				+	struct in6_addr in; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				791
			 | 
			
			
				
				+	struct net_device *netdev; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				792
			 | 
			
			
				
				+	size_t len; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				793
			 | 
			
			
				
				+	char *tmp; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				794
			 | 
			
			
				
				+	char *in_string; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				795
			 | 
			
			
				
				+	char *netdev_string; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				796
			 | 
			
			
				
				+	int rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				797
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				798
			 | 
			
			
				
				+	/* Create modifiable copy of string */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				799
			 | 
			
			
				
				+	tmp = strdup ( string ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				800
			 | 
			
			
				
				+	if ( ! tmp ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				801
			 | 
			
			
				
				+		rc = -ENOMEM; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				802
			 | 
			
			
				
				+		goto err_alloc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				803
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				804
			 | 
			
			
				
				+	in_string = tmp; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				805
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				806
			 | 
			
			
				
				+	/* Strip surrounding "[...]", if present */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				807
			 | 
			
			
				
				+	len = strlen ( in_string ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				808
			 | 
			
			
				
				+	if ( ( in_string[0] == '[' ) && ( in_string[ len - 1 ] == ']' ) ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				809
			 | 
			
			
				
				+		in_string[ len - 1 ] = '\0'; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				810
			 | 
			
			
				
				+		in_string++; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				811
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				812
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				813
			 | 
			
			
				
				+	/* Split at network device name, if present */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				814
			 | 
			
			
				
				+	netdev_string = strchr ( in_string, '%' ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				815
			 | 
			
			
				
				+	if ( netdev_string ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				816
			 | 
			
			
				
				+		*(netdev_string++) = '\0'; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				817
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				818
			 | 
			
			
				
				+	/* Parse IPv6 address portion */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				819
			 | 
			
			
				
				+	if ( ( rc = inet6_aton ( in_string, &in ) ) != 0 ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				820
			 | 
			
			
				
				+		goto err_inet6_aton; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				821
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				822
			 | 
			
			
				
				+	/* Parse network device name, if present */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				823
			 | 
			
			
				
				+	if ( netdev_string ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				824
			 | 
			
			
				
				+		netdev = find_netdev ( netdev_string ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				825
			 | 
			
			
				
				+		if ( ! netdev ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				826
			 | 
			
			
				
				+			rc = -ENODEV; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				827
			 | 
			
			
				
				+			goto err_find_netdev; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				828
			 | 
			
			
				
				+		} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				829
			 | 
			
			
				
				+		sin6->sin6_scope_id = netdev->index; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				830
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				831
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				832
			 | 
			
			
				
				+	/* Copy IPv6 address portion to socket address */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				833
			 | 
			
			
				
				+	memcpy ( &sin6->sin6_addr, &in, sizeof ( sin6->sin6_addr ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				834
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				835
			 | 
			
			
				
				+ err_find_netdev: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				836
			 | 
			
			
				
				+ err_inet6_aton: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				837
			 | 
			
			
				
				+	free ( tmp ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				838
			 | 
			
			
				
				+ err_alloc: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				839
			 | 
			
			
				
				+	return rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				840
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				841
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				752
			 | 
			
				842
			 | 
			
			
				
				 /** IPv6 protocol */ 
			 | 
		
		
	
		
			
			| 
				753
			 | 
			
				843
			 | 
			
			
				
				 struct net_protocol ipv6_protocol __net_protocol = { 
			 | 
		
		
	
		
			
			| 
				754
			 | 
			
				844
			 | 
			
			
				
				 	.name = "IPv6", 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -765,6 +855,13 @@ struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol = { 
			 | 
		
		
	
		
			
			| 
				765
			 | 
			
				855
			 | 
			
			
				
				 	.tx = ipv6_tx, 
			 | 
		
		
	
		
			
			| 
				766
			 | 
			
				856
			 | 
			
			
				
				 }; 
			 | 
		
		
	
		
			
			| 
				767
			 | 
			
				857
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				858
			 | 
			
			
				
				+/** IPv6 socket address converter */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				859
			 | 
			
			
				
				+struct sockaddr_converter ipv6_sockaddr_converter __sockaddr_converter = { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				860
			 | 
			
			
				
				+	.family = AF_INET6, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				861
			 | 
			
			
				
				+	.ntoa = ipv6_sock_ntoa, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				862
			 | 
			
			
				
				+	.aton = ipv6_sock_aton, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				863
			 | 
			
			
				
				+}; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				864
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				768
			 | 
			
				865
			 | 
			
			
				
				 /** 
			 | 
		
		
	
		
			
			| 
				769
			 | 
			
				866
			 | 
			
			
				
				  * Create IPv6 network device 
			 | 
		
		
	
		
			
			| 
				770
			 | 
			
				867
			 | 
			
			
				
				  * 
			 |