|
@@ -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
|
|