| 
				
			 | 
			
			
				
				@@ -1088,6 +1088,115 @@ const struct setting gateway6_setting __setting ( SETTING_IP6, gateway6 ) = { 
			 | 
		
		
	
		
			
			| 
				1088
			 | 
			
				1088
			 | 
			
			
				
				 	.scope = &ipv6_scope, 
			 | 
		
		
	
		
			
			| 
				1089
			 | 
			
				1089
			 | 
			
			
				
				 }; 
			 | 
		
		
	
		
			
			| 
				1090
			 | 
			
				1090
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1091
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1092
			 | 
			
			
				
				+ * Check applicability of IPv6 link-local address setting 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1093
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1094
			 | 
			
			
				
				+ * @v settings		Settings block 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1095
			 | 
			
			
				
				+ * @v setting		Setting to fetch 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1096
			 | 
			
			
				
				+ * @ret applies		Setting applies within this settings block 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1097
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1098
			 | 
			
			
				
				+static int ipv6_applies ( struct settings *settings __unused, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1099
			 | 
			
			
				
				+			  const struct setting *setting ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1100
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1101
			 | 
			
			
				
				+	return ( setting->scope == &ipv6_scope ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1102
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1103
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1104
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1105
			 | 
			
			
				
				+ * Fetch IPv6 link-local address setting 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1106
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1107
			 | 
			
			
				
				+ * @v settings		Settings block 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1108
			 | 
			
			
				
				+ * @v setting		Setting to fetch 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1109
			 | 
			
			
				
				+ * @v data		Buffer to fill with setting data 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1110
			 | 
			
			
				
				+ * @v len		Length of buffer 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1111
			 | 
			
			
				
				+ * @ret len		Length of setting data, or negative error 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1112
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1113
			 | 
			
			
				
				+static int ipv6_fetch ( struct settings *settings, struct setting *setting, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1114
			 | 
			
			
				
				+			void *data, size_t len ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1115
			 | 
			
			
				
				+	struct net_device *netdev = 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1116
			 | 
			
			
				
				+		container_of ( settings->parent, struct net_device, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1117
			 | 
			
			
				
				+			       settings.settings ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1118
			 | 
			
			
				
				+	struct in6_addr ip6; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1119
			 | 
			
			
				
				+	uint8_t *len6; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1120
			 | 
			
			
				
				+	int prefix_len; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1121
			 | 
			
			
				
				+	int rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1122
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1123
			 | 
			
			
				
				+	/* Construct link-local address from EUI-64 as per RFC 2464 */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1124
			 | 
			
			
				
				+	memset ( &ip6, 0, sizeof ( ip6 ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1125
			 | 
			
			
				
				+	prefix_len = ipv6_link_local ( &ip6, netdev ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1126
			 | 
			
			
				
				+	if ( prefix_len < 0 ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1127
			 | 
			
			
				
				+		rc = prefix_len; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1128
			 | 
			
			
				
				+		return rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1129
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1130
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1131
			 | 
			
			
				
				+	/* Handle setting */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1132
			 | 
			
			
				
				+	if ( setting_cmp ( setting, &ip6_setting ) == 0 ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1133
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1134
			 | 
			
			
				
				+		/* Return link-local ip6 */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1135
			 | 
			
			
				
				+		if ( len > sizeof ( ip6 ) ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1136
			 | 
			
			
				
				+			len = sizeof ( ip6 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1137
			 | 
			
			
				
				+		memcpy ( data, &ip6, len ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1138
			 | 
			
			
				
				+		return sizeof ( ip6 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1139
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1140
			 | 
			
			
				
				+	} else if ( setting_cmp ( setting, &len6_setting ) == 0 ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1141
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1142
			 | 
			
			
				
				+		/* Return prefix length */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1143
			 | 
			
			
				
				+		if ( len ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1144
			 | 
			
			
				
				+			len6 = data; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1145
			 | 
			
			
				
				+			*len6 = prefix_len; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1146
			 | 
			
			
				
				+		} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1147
			 | 
			
			
				
				+		return sizeof ( *len6 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1148
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1149
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1150
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1151
			 | 
			
			
				
				+	return -ENOENT; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1152
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1153
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1154
			 | 
			
			
				
				+/** IPv6 link-local address settings operations */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1155
			 | 
			
			
				
				+static struct settings_operations ipv6_settings_operations = { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1156
			 | 
			
			
				
				+	.applies = ipv6_applies, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1157
			 | 
			
			
				
				+	.fetch = ipv6_fetch, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1158
			 | 
			
			
				
				+}; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1159
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1160
			 | 
			
			
				
				+/** IPv6 link-local address settings */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1161
			 | 
			
			
				
				+struct ipv6_settings { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1162
			 | 
			
			
				
				+	/** Reference counter */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1163
			 | 
			
			
				
				+	struct refcnt refcnt; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1164
			 | 
			
			
				
				+	/** Settings interface */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1165
			 | 
			
			
				
				+	struct settings settings; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1166
			 | 
			
			
				
				+}; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1167
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1168
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1169
			 | 
			
			
				
				+ * Register IPv6 link-local address settings 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1170
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1171
			 | 
			
			
				
				+ * @v netdev		Network device 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1172
			 | 
			
			
				
				+ * @ret rc		Return status code 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1173
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1174
			 | 
			
			
				
				+static int ipv6_register_settings ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1175
			 | 
			
			
				
				+	struct settings *parent = netdev_settings ( netdev ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1176
			 | 
			
			
				
				+	struct ipv6_settings *ipv6set; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1177
			 | 
			
			
				
				+	int rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1178
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1179
			 | 
			
			
				
				+	/* Allocate and initialise structure */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1180
			 | 
			
			
				
				+	ipv6set = zalloc ( sizeof ( *ipv6set ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1181
			 | 
			
			
				
				+	if ( ! ipv6set ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1182
			 | 
			
			
				
				+		rc = -ENOMEM; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1183
			 | 
			
			
				
				+		goto err_alloc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1184
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1185
			 | 
			
			
				
				+	ref_init ( &ipv6set->refcnt, NULL ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1186
			 | 
			
			
				
				+	settings_init ( &ipv6set->settings, &ipv6_settings_operations, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1187
			 | 
			
			
				
				+			&ipv6set->refcnt, &ipv6_scope ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1188
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1189
			 | 
			
			
				
				+	/* Register settings */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1190
			 | 
			
			
				
				+	if ( ( rc = register_settings ( &ipv6set->settings, parent, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1191
			 | 
			
			
				
				+					IPV6_SETTINGS_NAME ) ) != 0 ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1192
			 | 
			
			
				
				+		goto err_register; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1193
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1194
			 | 
			
			
				
				+ err_register: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1195
			 | 
			
			
				
				+	ref_put ( &ipv6set->refcnt ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1196
			 | 
			
			
				
				+ err_alloc: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1197
			 | 
			
			
				
				+	return rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1198
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1199
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				1091
			 | 
			
				1200
			 | 
			
			
				
				 /** 
			 | 
		
		
	
		
			
			| 
				1092
			 | 
			
				1201
			 | 
			
			
				
				  * Create IPv6 network device 
			 | 
		
		
	
		
			
			| 
				1093
			 | 
			
				1202
			 | 
			
			
				
				  * 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -1116,6 +1225,10 @@ static int ipv6_probe ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				1116
			 | 
			
				1225
			 | 
			
			
				
				 	if ( ! miniroute ) 
			 | 
		
		
	
		
			
			| 
				1117
			 | 
			
				1226
			 | 
			
			
				
				 		return -ENOMEM; 
			 | 
		
		
	
		
			
			| 
				1118
			 | 
			
				1227
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1228
			 | 
			
			
				
				+	/* Register link-local address settings */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1229
			 | 
			
			
				
				+	if ( ( rc = ipv6_register_settings ( netdev ) ) != 0 ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1230
			 | 
			
			
				
				+		return rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1231
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				1119
			 | 
			
				1232
			 | 
			
			
				
				 	return 0; 
			 | 
		
		
	
		
			
			| 
				1120
			 | 
			
				1233
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				1121
			 | 
			
				1234
			 | 
			
			
				
				  
			 |