Browse Source

[ipv6] Separate the concepts of prefix and address creation

Allow for IPv6 routing table entries to be created for an on-link
prefix where a local address has not yet been assigned to the network
device.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
6b1eee0452
4 changed files with 201 additions and 124 deletions
  1. 15
    5
      src/include/ipxe/ipv6.h
  2. 120
    84
      src/net/ipv6.c
  3. 63
    34
      src/net/ndp.c
  4. 3
    1
      src/usr/route_ipv6.c

+ 15
- 5
src/include/ipxe/ipv6.h View File

@@ -160,16 +160,24 @@ struct ipv6_miniroute {
160 160
 	/** Network device */
161 161
 	struct net_device *netdev;
162 162
 
163
-	/** IPv6 address */
163
+	/** IPv6 address (or prefix if no address is defined) */
164 164
 	struct in6_addr address;
165 165
 	/** Prefix length */
166 166
 	unsigned int prefix_len;
167 167
 	/** IPv6 prefix mask (derived from prefix length) */
168 168
 	struct in6_addr prefix_mask;
169
-	/** Router address is present */
170
-	int has_router;
171 169
 	/** Router address */
172 170
 	struct in6_addr router;
171
+	/** Flags */
172
+	unsigned int flags;
173
+};
174
+
175
+/** IPv6 address/routing table entry flags */
176
+enum ipv6_miniroute_flags {
177
+	/** Routing table entry address is valid */
178
+	IPV6_HAS_ADDRESS = 0x0001,
179
+	/** Routing table entry router address is valid */
180
+	IPV6_HAS_ROUTER = 0x0002,
173 181
 };
174 182
 
175 183
 /**
@@ -235,7 +243,9 @@ extern struct list_head ipv6_miniroutes;
235 243
 extern struct net_protocol ipv6_protocol __net_protocol;
236 244
 
237 245
 extern int ipv6_has_addr ( struct net_device *netdev, struct in6_addr *addr );
238
-extern int ipv6_slaac ( struct net_device *netdev, struct in6_addr *prefix,
239
-			unsigned int prefix_len, struct in6_addr *router );
246
+extern int ipv6_set_prefix ( struct net_device *netdev, struct in6_addr *prefix,
247
+			     unsigned int prefix_len, struct in6_addr *router );
248
+extern int ipv6_set_address ( struct net_device *netdev,
249
+			      struct in6_addr *address );
240 250
 
241 251
 #endif /* _IPXE_IPV6_H */

+ 120
- 84
src/net/ipv6.c View File

@@ -67,6 +67,24 @@ static uint32_t ipv6col ( struct in6_addr *in ) {
67 67
 	return crc32_le ( 0, in, sizeof ( *in ) );
68 68
 }
69 69
 
70
+/**
71
+ * Dump IPv6 routing table entry
72
+ *
73
+ * @v miniroute		Routing table entry
74
+ */
75
+static inline __attribute__ (( always_inline )) void
76
+ipv6_dump_miniroute ( struct ipv6_miniroute *miniroute ) {
77
+	struct net_device *netdev = miniroute->netdev;
78
+
79
+	DBGC ( netdev, "IPv6 %s has %s %s/%d", netdev->name,
80
+	       ( ( miniroute->flags & IPV6_HAS_ADDRESS ) ?
81
+		 "address" : "prefix" ),
82
+	       inet6_ntoa ( &miniroute->address ), miniroute->prefix_len );
83
+	if ( miniroute->flags & IPV6_HAS_ROUTER )
84
+		DBGC ( netdev, " router %s", inet6_ntoa ( &miniroute->router ));
85
+	DBGC ( netdev, "\n" );
86
+}
87
+
70 88
 /**
71 89
  * Check if network device has a specific IPv6 address
72 90
  *
@@ -79,6 +97,7 @@ int ipv6_has_addr ( struct net_device *netdev, struct in6_addr *addr ) {
79 97
 
80 98
 	list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
81 99
 		if ( ( miniroute->netdev == netdev ) &&
100
+		     ( miniroute->flags & IPV6_HAS_ADDRESS ) &&
82 101
 		     ( memcmp ( &miniroute->address, addr,
83 102
 				sizeof ( miniroute->address ) ) == 0 ) ) {
84 103
 			/* Found matching address */
@@ -109,31 +128,45 @@ static int ipv6_is_on_link ( struct ipv6_miniroute *miniroute,
109 128
 }
110 129
 
111 130
 /**
112
- * Add IPv6 minirouting table entry
131
+ * Find IPv6 routing table entry for a given address
113 132
  *
114 133
  * @v netdev		Network device
115 134
  * @v address		IPv6 address
135
+ * @ret miniroute	Routing table entry, or NULL if not found
136
+ */
137
+static struct ipv6_miniroute * ipv6_miniroute ( struct net_device *netdev,
138
+						struct in6_addr *address ) {
139
+	struct ipv6_miniroute *miniroute;
140
+
141
+	list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
142
+		if ( ( miniroute->netdev == netdev ) &&
143
+		     ipv6_is_on_link ( miniroute, address ) ) {
144
+			return miniroute;
145
+		}
146
+	}
147
+	return NULL;
148
+}
149
+
150
+/**
151
+ * Add IPv6 routing table entry
152
+ *
153
+ * @v netdev		Network device
154
+ * @v address		IPv6 address (or prefix)
116 155
  * @v prefix_len	Prefix length
117
- * @v router		Router address (or NULL)
156
+ * @v flags		Flags
118 157
  * @ret miniroute	Routing table entry, or NULL on failure
119 158
  */
120
-static struct ipv6_miniroute * __malloc
121
-add_ipv6_miniroute ( struct net_device *netdev, struct in6_addr *address,
122
-		     unsigned int prefix_len, struct in6_addr *router ) {
159
+static struct ipv6_miniroute * ipv6_add_miniroute ( struct net_device *netdev,
160
+						    struct in6_addr *address,
161
+						    unsigned int prefix_len,
162
+						    unsigned int flags ) {
123 163
 	struct ipv6_miniroute *miniroute;
124 164
 	uint8_t *prefix_mask;
125 165
 
126
-	DBGC ( netdev, "IPv6 add %s/%d ", inet6_ntoa ( address ), prefix_len );
127
-	if ( router )
128
-		DBGC ( netdev, "router %s ", inet6_ntoa ( router ) );
129
-	DBGC ( netdev, "via %s\n", netdev->name );
130
-
131
-	/* Allocate and populate miniroute structure */
166
+	/* Create routing table entry */
132 167
 	miniroute = zalloc ( sizeof ( *miniroute ) );
133 168
 	if ( ! miniroute )
134 169
 		return NULL;
135
-
136
-	/* Record routing information */
137 170
 	miniroute->netdev = netdev_get ( netdev );
138 171
 	memcpy ( &miniroute->address, address, sizeof ( miniroute->address ) );
139 172
 	miniroute->prefix_len = prefix_len;
@@ -144,41 +177,83 @@ add_ipv6_miniroute ( struct net_device *netdev, struct in6_addr *address,
144 177
 	}
145 178
 	if ( prefix_len )
146 179
 		*prefix_mask <<= ( 8 - prefix_len );
180
+	miniroute->flags = flags;
181
+	list_add ( &miniroute->list, &ipv6_miniroutes );
182
+	ipv6_dump_miniroute ( miniroute );
183
+
184
+	return miniroute;
185
+}
186
+
187
+/**
188
+ * Define IPv6 on-link prefix
189
+ *
190
+ * @v netdev		Network device
191
+ * @v prefix		IPv6 address prefix
192
+ * @v prefix_len	Prefix length
193
+ * @v router		Router address (or NULL)
194
+ * @ret rc		Return status code
195
+ */
196
+int ipv6_set_prefix ( struct net_device *netdev, struct in6_addr *prefix,
197
+		      unsigned int prefix_len, struct in6_addr *router ) {
198
+	struct ipv6_miniroute *miniroute;
199
+	int changed;
200
+
201
+	/* Find or create routing table entry */
202
+	miniroute = ipv6_miniroute ( netdev, prefix );
203
+	if ( ! miniroute )
204
+		miniroute = ipv6_add_miniroute ( netdev, prefix, prefix_len, 0);
205
+	if ( ! miniroute )
206
+		return -ENOMEM;
207
+
208
+	/* Record router and add to start or end of list as appropriate */
209
+	list_del ( &miniroute->list );
147 210
 	if ( router ) {
148
-		miniroute->has_router = 1;
211
+		changed = ( ( ! ( miniroute->flags & IPV6_HAS_ROUTER ) ) ||
212
+			    ( memcmp ( &miniroute->router, router,
213
+				       sizeof ( miniroute->router ) ) != 0 ) );
214
+		miniroute->flags |= IPV6_HAS_ROUTER;
149 215
 		memcpy ( &miniroute->router, router,
150 216
 			 sizeof ( miniroute->router ) );
151
-	}
152
-
153
-	/* Add to end of list if we have a gateway, otherwise to start
154
-	 * of list.
155
-	 */
156
-	if ( router ) {
157 217
 		list_add_tail ( &miniroute->list, &ipv6_miniroutes );
158 218
 	} else {
219
+		changed = ( miniroute->flags & IPV6_HAS_ROUTER );
220
+		miniroute->flags &= ~IPV6_HAS_ROUTER;
159 221
 		list_add ( &miniroute->list, &ipv6_miniroutes );
160 222
 	}
223
+	if ( changed )
224
+		ipv6_dump_miniroute ( miniroute );
161 225
 
162
-	return miniroute;
226
+	return 0;
163 227
 }
164 228
 
165 229
 /**
166
- * Delete IPv6 minirouting table entry
230
+ * Add IPv6 on-link address
167 231
  *
168
- * @v miniroute		Routing table entry
232
+ * @v netdev		Network device
233
+ * @v address		IPv6 address
234
+ * @ret rc		Return status code
235
+ *
236
+ * An on-link prefix for the address must already exist.
169 237
  */
170
-static void del_ipv6_miniroute ( struct ipv6_miniroute *miniroute ) {
171
-	struct net_device *netdev = miniroute->netdev;
238
+int ipv6_set_address ( struct net_device *netdev, struct in6_addr *address ) {
239
+	struct ipv6_miniroute *miniroute;
240
+	int changed;
241
+
242
+	/* Find routing table entry */
243
+	miniroute = ipv6_miniroute ( netdev, address );
244
+	if ( ! miniroute )
245
+		return -EADDRNOTAVAIL;
172 246
 
173
-	DBGC ( netdev, "IPv6 del %s/%d ", inet6_ntoa ( &miniroute->address ),
174
-	       miniroute->prefix_len );
175
-	if ( miniroute->has_router )
176
-		DBGC ( netdev, "router %s ", inet6_ntoa ( &miniroute->router ));
177
-	DBGC ( netdev, "via %s\n", netdev->name );
247
+	/* Record address */
248
+	changed = ( ( ! ( miniroute->flags & IPV6_HAS_ADDRESS ) ) ||
249
+		    ( memcmp ( &miniroute->address, address,
250
+			       sizeof ( miniroute->address ) ) != 0 ) );
251
+	memcpy ( &miniroute->address, address, sizeof ( miniroute->address ) );
252
+	miniroute->flags |= IPV6_HAS_ADDRESS;
253
+	if ( changed )
254
+		ipv6_dump_miniroute ( miniroute );
178 255
 
179
-	netdev_put ( miniroute->netdev );
180
-	list_del ( &miniroute->list );
181
-	free ( miniroute );
256
+	return 0;
182 257
 }
183 258
 
184 259
 /**
@@ -200,6 +275,10 @@ static struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
200 275
 		if ( ! netdev_is_open ( miniroute->netdev ) )
201 276
 			continue;
202 277
 
278
+		/* Skip routing table entries with no usable source address */
279
+		if ( ! ( miniroute->flags & IPV6_HAS_ADDRESS ) )
280
+			continue;
281
+
203 282
 		if ( IN6_IS_ADDR_LINKLOCAL ( *dest ) ||
204 283
 		     IN6_IS_ADDR_MULTICAST ( *dest ) ) {
205 284
 
@@ -221,7 +300,7 @@ static struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
221 300
 			 * address, and we have a default gateway,
222 301
 			 * then use this route.
223 302
 			 */
224
-			if ( miniroute->has_router ) {
303
+			if ( miniroute->flags & IPV6_HAS_ROUTER ) {
225 304
 				*dest = &miniroute->router;
226 305
 				return miniroute;
227 306
 			}
@@ -919,53 +998,6 @@ struct setting_type setting_type_ipv6 __setting_type = {
919 998
 	.format = format_ipv6_setting,
920 999
 };
921 1000
 
922
-/**
923
- * Perform IPv6 stateless address autoconfiguration (SLAAC)
924
- *
925
- * @v netdev		Network device
926
- * @v prefix		Prefix
927
- * @v prefix_len	Prefix length
928
- * @v router		Router address (or NULL)
929
- * @ret rc		Return status code
930
- */
931
-int ipv6_slaac ( struct net_device *netdev, struct in6_addr *prefix,
932
-		 unsigned int prefix_len, struct in6_addr *router ) {
933
-	struct ipv6_miniroute *miniroute;
934
-	struct ipv6_miniroute *tmp;
935
-	struct in6_addr address;
936
-	int check_prefix_len;
937
-	int rc;
938
-
939
-	/* Construct local address */
940
-	memcpy ( &address, prefix, sizeof ( address ) );
941
-	check_prefix_len = ipv6_eui64 ( &address, netdev );
942
-	if ( check_prefix_len < 0 ) {
943
-		rc = check_prefix_len;
944
-		DBGC ( netdev, "IPv6 %s could not construct SLAAC address: "
945
-		       "%s\n", netdev->name, strerror ( rc ) );
946
-		return rc;
947
-	}
948
-	if ( check_prefix_len != ( int ) prefix_len ) {
949
-		DBGC ( netdev, "IPv6 %s incorrect SLAAC prefix length %d "
950
-		       "(expected %d)\n", netdev->name, prefix_len,
951
-		       check_prefix_len );
952
-		return -EINVAL;
953
-	}
954
-
955
-	/* Delete any existing SLAAC miniroutes for this prefix */
956
-	list_for_each_entry_safe ( miniroute, tmp, &ipv6_miniroutes, list ) {
957
-		if ( ipv6_is_on_link ( miniroute, &address ) )
958
-			del_ipv6_miniroute ( miniroute );
959
-	}
960
-
961
-	/* Add miniroute */
962
-	miniroute = add_ipv6_miniroute ( netdev, &address, prefix_len, router );
963
-	if ( ! miniroute )
964
-		return -ENOMEM;
965
-
966
-	return 0;
967
-}
968
-
969 1001
 /**
970 1002
  * Create IPv6 network device
971 1003
  *
@@ -989,7 +1021,8 @@ static int ipv6_probe ( struct net_device *netdev ) {
989 1021
 	}
990 1022
 
991 1023
 	/* Create link-local address for this network device */
992
-	miniroute = add_ipv6_miniroute ( netdev, &address, prefix_len, NULL );
1024
+	miniroute = ipv6_add_miniroute ( netdev, &address, prefix_len,
1025
+					 IPV6_HAS_ADDRESS );
993 1026
 	if ( ! miniroute )
994 1027
 		return -ENOMEM;
995 1028
 
@@ -1007,8 +1040,11 @@ static void ipv6_remove ( struct net_device *netdev ) {
1007 1040
 
1008 1041
 	/* Delete all miniroutes for this network device */
1009 1042
 	list_for_each_entry_safe ( miniroute, tmp, &ipv6_miniroutes, list ) {
1010
-		if ( miniroute->netdev == netdev )
1011
-			del_ipv6_miniroute ( miniroute );
1043
+		if ( miniroute->netdev == netdev ) {
1044
+			netdev_put ( miniroute->netdev );
1045
+			list_del ( &miniroute->list );
1046
+			free ( miniroute );
1047
+		}
1012 1048
 	}
1013 1049
 }
1014 1050
 

+ 63
- 34
src/net/ndp.c View File

@@ -88,8 +88,8 @@ static int ndp_tx_ll_addr ( struct net_device *netdev,
88 88
 	/* Transmit packet */
89 89
 	if ( ( rc = tcpip_tx ( iobuf, &icmpv6_protocol, st_src, st_dest,
90 90
 			       netdev, &ndp->icmp.chksum ) ) != 0 ) {
91
-		DBGC ( netdev, "NDP could not transmit packet: %s\n",
92
-		       strerror ( rc ) );
91
+		DBGC ( netdev, "NDP %s could not transmit packet: %s\n",
92
+		       netdev->name, strerror ( rc ) );
93 93
 		return rc;
94 94
 	}
95 95
 
@@ -205,8 +205,9 @@ ndp_rx_neighbour_solicitation_ll_source ( struct net_device *netdev,
205 205
 	/* Sanity check */
206 206
 	if ( offsetof ( typeof ( *ll_addr_opt ),
207 207
 			ll_addr[ll_protocol->ll_addr_len] ) > len ) {
208
-		DBGC ( netdev, "NDP neighbour solicitation link-layer address "
209
-		       "option too short at %zd bytes\n", len );
208
+		DBGC ( netdev, "NDP %s neighbour solicitation link-layer "
209
+		       "address option too short at %zd bytes\n",
210
+		       netdev->name, len );
210 211
 		return -EINVAL;
211 212
 	}
212 213
 
@@ -214,8 +215,8 @@ ndp_rx_neighbour_solicitation_ll_source ( struct net_device *netdev,
214 215
 	if ( ( rc = neighbour_define ( netdev, &ipv6_protocol,
215 216
 				       &sin6_src->sin6_addr,
216 217
 				       ll_addr_opt->ll_addr ) ) != 0 ) {
217
-		DBGC ( netdev, "NDP could not define %s => %s: %s\n",
218
-		       inet6_ntoa ( &sin6_src->sin6_addr ),
218
+		DBGC ( netdev, "NDP %s could not define %s => %s: %s\n",
219
+		       netdev->name, inet6_ntoa ( &sin6_src->sin6_addr ),
219 220
 		       ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
220 221
 		       strerror ( rc ) );
221 222
 		return rc;
@@ -260,16 +261,17 @@ ndp_rx_neighbour_advertisement_ll_target ( struct net_device *netdev,
260 261
 	/* Sanity check */
261 262
 	if ( offsetof ( typeof ( *ll_addr_opt ),
262 263
 			ll_addr[ll_protocol->ll_addr_len] ) > len ) {
263
-		DBGC ( netdev, "NDP neighbour advertisement link-layer address "
264
-		       "option too short at %zd bytes\n", len );
264
+		DBGC ( netdev, "NDP %s neighbour advertisement link-layer "
265
+		       "address option too short at %zd bytes\n",
266
+		       netdev->name, len );
265 267
 		return -EINVAL;
266 268
 	}
267 269
 
268 270
 	/* Update neighbour cache entry, if any */
269 271
 	if ( ( rc = neighbour_update ( netdev, &ipv6_protocol, &neigh->target,
270 272
 				       ll_addr_opt->ll_addr ) ) != 0 ) {
271
-		DBGC ( netdev, "NDP could not update %s => %s: %s\n",
272
-		       inet6_ntoa ( &neigh->target ),
273
+		DBGC ( netdev, "NDP %s could not update %s => %s: %s\n",
274
+		       netdev->name, inet6_ntoa ( &neigh->target ),
273 275
 		       ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
274 276
 		       strerror ( rc ) );
275 277
 		return rc;
@@ -300,8 +302,8 @@ ndp_rx_router_advertisement_ll_source ( struct net_device *netdev,
300 302
 	/* Sanity check */
301 303
 	if ( offsetof ( typeof ( *ll_addr_opt ),
302 304
 			ll_addr[ll_protocol->ll_addr_len] ) > len ) {
303
-		DBGC ( netdev, "NDP router advertisement link-layer address "
304
-		       "option too short at %zd bytes\n", len );
305
+		DBGC ( netdev, "NDP %s router advertisement link-layer address "
306
+		       "option too short at %zd bytes\n", netdev->name, len );
305 307
 		return -EINVAL;
306 308
 	}
307 309
 
@@ -309,8 +311,8 @@ ndp_rx_router_advertisement_ll_source ( struct net_device *netdev,
309 311
 	if ( ( rc = neighbour_define ( netdev, &ipv6_protocol,
310 312
 				       &sin6_src->sin6_addr,
311 313
 				       ll_addr_opt->ll_addr ) ) != 0 ) {
312
-		DBGC ( netdev, "NDP could not define %s => %s: %s\n",
313
-		       inet6_ntoa ( &sin6_src->sin6_addr ),
314
+		DBGC ( netdev, "NDP %s could not define %s => %s: %s\n",
315
+		       netdev->name, inet6_ntoa ( &sin6_src->sin6_addr ),
314 316
 		       ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
315 317
 		       strerror ( rc ) );
316 318
 		return rc;
@@ -337,16 +339,18 @@ ndp_rx_router_advertisement_prefix ( struct net_device *netdev,
337 339
 	struct ndp_router_advertisement_header *radv = &ndp->radv;
338 340
 	struct ndp_prefix_information_option *prefix_opt = &option->prefix;
339 341
 	struct in6_addr *router = &sin6_src->sin6_addr;
342
+	struct in6_addr address;
343
+	int prefix_len;
340 344
 	int rc;
341 345
 
342 346
 	/* Sanity check */
343 347
 	if ( sizeof ( *prefix_opt ) > len ) {
344
-		DBGC ( netdev, "NDP router advertisement prefix option too "
345
-		       "short at %zd bytes\n", len );
348
+		DBGC ( netdev, "NDP %s router advertisement prefix option too "
349
+		       "short at %zd bytes\n", netdev->name, len );
346 350
 		return -EINVAL;
347 351
 	}
348
-	DBGC ( netdev, "NDP found %sdefault router %s ",
349
-	       ( radv->lifetime ? "" : "non-" ),
352
+	DBGC ( netdev, "NDP %s found %sdefault router %s ",
353
+	       netdev->name, ( radv->lifetime ? "" : "non-" ),
350 354
 	       inet6_ntoa ( &sin6_src->sin6_addr ) );
351 355
 	DBGC ( netdev, "for %s-link %sautonomous prefix %s/%d\n",
352 356
 	       ( ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) ? "on" : "off" ),
@@ -354,17 +358,41 @@ ndp_rx_router_advertisement_prefix ( struct net_device *netdev,
354 358
 	       inet6_ntoa ( &prefix_opt->prefix ),
355 359
 	       prefix_opt->prefix_len );
356 360
 
361
+	/* Ignore off-link prefixes */
362
+	if ( ! ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) )
363
+		return 0;
364
+
365
+	/* Define prefix */
366
+	if ( ( rc = ipv6_set_prefix ( netdev, &prefix_opt->prefix,
367
+				      prefix_opt->prefix_len,
368
+				      ( radv->lifetime ?
369
+					router : NULL ) ) ) != 0 ) {
370
+		DBGC ( netdev, "NDP %s could not define prefix %s/%d: %s\n",
371
+		       netdev->name, inet6_ntoa ( &prefix_opt->prefix ),
372
+		       prefix_opt->prefix_len, strerror ( rc ) );
373
+		return rc;
374
+	}
375
+
357 376
 	/* Perform stateless address autoconfiguration, if applicable */
358
-	if ( ( prefix_opt->flags &
359
-	       ( NDP_PREFIX_ON_LINK | NDP_PREFIX_AUTONOMOUS ) ) ==
360
-	     ( NDP_PREFIX_ON_LINK | NDP_PREFIX_AUTONOMOUS ) ) {
361
-		if ( ( rc = ipv6_slaac ( netdev, &prefix_opt->prefix,
362
-					 prefix_opt->prefix_len,
363
-					 ( radv->lifetime ?
364
-					   router : NULL ) ) ) != 0 ) {
365
-			DBGC ( netdev, "NDP could not autoconfigure prefix %s/"
366
-			       "%d: %s\n", inet6_ntoa ( &prefix_opt->prefix ),
367
-			       prefix_opt->prefix_len, strerror ( rc ) );
377
+	if ( prefix_opt->flags & NDP_PREFIX_AUTONOMOUS ) {
378
+		memcpy ( &address, &prefix_opt->prefix, sizeof ( address ) );
379
+		prefix_len = ipv6_eui64 ( &address, netdev );
380
+		if ( prefix_len < 0 ) {
381
+			rc = prefix_len;
382
+			DBGC ( netdev, "NDP %s could not construct SLAAC "
383
+			       "address: %s\n", netdev->name, strerror ( rc ) );
384
+			return rc;
385
+		}
386
+		if ( prefix_len != prefix_opt->prefix_len ) {
387
+			DBGC ( netdev, "NDP %s incorrect SLAAC prefix length "
388
+			       "%d (expected %d)\n", netdev->name,
389
+			       prefix_opt->prefix_len, prefix_len );
390
+			return -EINVAL;
391
+		}
392
+		if ( ( rc = ipv6_set_address ( netdev, &address ) ) != 0 ) {
393
+			DBGC ( netdev, "NDP %s could not set address %s: %s\n",
394
+			       netdev->name, inet6_ntoa ( &address ),
395
+			       strerror ( rc ) );
368 396
 			return rc;
369 397
 		}
370 398
 	}
@@ -467,8 +495,8 @@ static int ndp_rx_options ( struct net_device *netdev,
467 495
 
468 496
 	/* Sanity check */
469 497
 	if ( len < offset ) {
470
-		DBGC ( netdev, "NDP packet too short at %zd bytes (min %zd "
471
-		       "bytes)\n", len, offset );
498
+		DBGC ( netdev, "NDP %s packet too short at %zd bytes (min %zd "
499
+		       "bytes)\n", netdev->name, len, offset );
472 500
 		return -EINVAL;
473 501
 	}
474 502
 
@@ -482,7 +510,8 @@ static int ndp_rx_options ( struct net_device *netdev,
482 510
 		     ( option->header.blocks == 0 ) ||
483 511
 		     ( remaining < ( option->header.blocks *
484 512
 				     NDP_OPTION_BLKSZ ) ) ) {
485
-			DBGC ( netdev, "NDP bad option length:\n" );
513
+			DBGC ( netdev, "NDP %s bad option length:\n",
514
+			       netdev->name );
486 515
 			DBGC_HDA ( netdev, 0, option, remaining );
487 516
 			return -EINVAL;
488 517
 		}
@@ -715,9 +744,9 @@ static int ipv6conf_rx_router_advertisement ( struct net_device *netdev,
715 744
 		stateful = ( flags & NDP_ROUTER_MANAGED );
716 745
 		if ( ( rc = start_dhcpv6 ( &ipv6conf->dhcp, netdev,
717 746
 					   stateful ) ) != 0 ) {
718
-			DBGC ( netdev, "NDP could not start state%s DHCPv6: "
719
-			       "%s\n", ( stateful ? "ful" : "less" ),
720
-			       strerror ( rc ) );
747
+			DBGC ( netdev, "NDP %s could not start state%s DHCPv6: "
748
+			       "%s\n", netdev->name,
749
+			       ( stateful ? "ful" : "less" ), strerror ( rc ) );
721 750
 			ipv6conf_done ( ipv6conf, rc );
722 751
 			return rc;
723 752
 		}

+ 3
- 1
src/usr/route_ipv6.c View File

@@ -44,8 +44,10 @@ static void route_ipv6_print ( struct net_device *netdev ) {
44 44
 		printf ( "%s: %s/%d", netdev->name,
45 45
 			 inet6_ntoa ( &miniroute->address ),
46 46
 			 miniroute->prefix_len );
47
-		if ( miniroute->has_router )
47
+		if ( miniroute->flags & IPV6_HAS_ROUTER )
48 48
 			printf ( " gw %s", inet6_ntoa ( &miniroute->router ) );
49
+		if ( ! ( miniroute->flags & IPV6_HAS_ADDRESS ) )
50
+			printf ( " (no address)" );
49 51
 		if ( ! netdev_is_open ( miniroute->netdev ) )
50 52
 			printf ( " (inaccessible)" );
51 53
 		printf ( "\n" );

Loading…
Cancel
Save