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 11 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
 	/** Network device */
160
 	/** Network device */
161
 	struct net_device *netdev;
161
 	struct net_device *netdev;
162
 
162
 
163
-	/** IPv6 address */
163
+	/** IPv6 address (or prefix if no address is defined) */
164
 	struct in6_addr address;
164
 	struct in6_addr address;
165
 	/** Prefix length */
165
 	/** Prefix length */
166
 	unsigned int prefix_len;
166
 	unsigned int prefix_len;
167
 	/** IPv6 prefix mask (derived from prefix length) */
167
 	/** IPv6 prefix mask (derived from prefix length) */
168
 	struct in6_addr prefix_mask;
168
 	struct in6_addr prefix_mask;
169
-	/** Router address is present */
170
-	int has_router;
171
 	/** Router address */
169
 	/** Router address */
172
 	struct in6_addr router;
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
 extern struct net_protocol ipv6_protocol __net_protocol;
243
 extern struct net_protocol ipv6_protocol __net_protocol;
236
 
244
 
237
 extern int ipv6_has_addr ( struct net_device *netdev, struct in6_addr *addr );
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
 #endif /* _IPXE_IPV6_H */
251
 #endif /* _IPXE_IPV6_H */

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

67
 	return crc32_le ( 0, in, sizeof ( *in ) );
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
  * Check if network device has a specific IPv6 address
89
  * Check if network device has a specific IPv6 address
72
  *
90
  *
79
 
97
 
80
 	list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
98
 	list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
81
 		if ( ( miniroute->netdev == netdev ) &&
99
 		if ( ( miniroute->netdev == netdev ) &&
100
+		     ( miniroute->flags & IPV6_HAS_ADDRESS ) &&
82
 		     ( memcmp ( &miniroute->address, addr,
101
 		     ( memcmp ( &miniroute->address, addr,
83
 				sizeof ( miniroute->address ) ) == 0 ) ) {
102
 				sizeof ( miniroute->address ) ) == 0 ) ) {
84
 			/* Found matching address */
103
 			/* Found matching address */
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
  * @v netdev		Network device
133
  * @v netdev		Network device
115
  * @v address		IPv6 address
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
  * @v prefix_len	Prefix length
155
  * @v prefix_len	Prefix length
117
- * @v router		Router address (or NULL)
156
+ * @v flags		Flags
118
  * @ret miniroute	Routing table entry, or NULL on failure
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
 	struct ipv6_miniroute *miniroute;
163
 	struct ipv6_miniroute *miniroute;
124
 	uint8_t *prefix_mask;
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
 	miniroute = zalloc ( sizeof ( *miniroute ) );
167
 	miniroute = zalloc ( sizeof ( *miniroute ) );
133
 	if ( ! miniroute )
168
 	if ( ! miniroute )
134
 		return NULL;
169
 		return NULL;
135
-
136
-	/* Record routing information */
137
 	miniroute->netdev = netdev_get ( netdev );
170
 	miniroute->netdev = netdev_get ( netdev );
138
 	memcpy ( &miniroute->address, address, sizeof ( miniroute->address ) );
171
 	memcpy ( &miniroute->address, address, sizeof ( miniroute->address ) );
139
 	miniroute->prefix_len = prefix_len;
172
 	miniroute->prefix_len = prefix_len;
144
 	}
177
 	}
145
 	if ( prefix_len )
178
 	if ( prefix_len )
146
 		*prefix_mask <<= ( 8 - prefix_len );
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
 	if ( router ) {
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
 		memcpy ( &miniroute->router, router,
215
 		memcpy ( &miniroute->router, router,
150
 			 sizeof ( miniroute->router ) );
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
 		list_add_tail ( &miniroute->list, &ipv6_miniroutes );
217
 		list_add_tail ( &miniroute->list, &ipv6_miniroutes );
158
 	} else {
218
 	} else {
219
+		changed = ( miniroute->flags & IPV6_HAS_ROUTER );
220
+		miniroute->flags &= ~IPV6_HAS_ROUTER;
159
 		list_add ( &miniroute->list, &ipv6_miniroutes );
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
 		if ( ! netdev_is_open ( miniroute->netdev ) )
275
 		if ( ! netdev_is_open ( miniroute->netdev ) )
201
 			continue;
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
 		if ( IN6_IS_ADDR_LINKLOCAL ( *dest ) ||
282
 		if ( IN6_IS_ADDR_LINKLOCAL ( *dest ) ||
204
 		     IN6_IS_ADDR_MULTICAST ( *dest ) ) {
283
 		     IN6_IS_ADDR_MULTICAST ( *dest ) ) {
205
 
284
 
221
 			 * address, and we have a default gateway,
300
 			 * address, and we have a default gateway,
222
 			 * then use this route.
301
 			 * then use this route.
223
 			 */
302
 			 */
224
-			if ( miniroute->has_router ) {
303
+			if ( miniroute->flags & IPV6_HAS_ROUTER ) {
225
 				*dest = &miniroute->router;
304
 				*dest = &miniroute->router;
226
 				return miniroute;
305
 				return miniroute;
227
 			}
306
 			}
919
 	.format = format_ipv6_setting,
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
  * Create IPv6 network device
1002
  * Create IPv6 network device
971
  *
1003
  *
989
 	}
1021
 	}
990
 
1022
 
991
 	/* Create link-local address for this network device */
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
 	if ( ! miniroute )
1026
 	if ( ! miniroute )
994
 		return -ENOMEM;
1027
 		return -ENOMEM;
995
 
1028
 
1007
 
1040
 
1008
 	/* Delete all miniroutes for this network device */
1041
 	/* Delete all miniroutes for this network device */
1009
 	list_for_each_entry_safe ( miniroute, tmp, &ipv6_miniroutes, list ) {
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
 	/* Transmit packet */
88
 	/* Transmit packet */
89
 	if ( ( rc = tcpip_tx ( iobuf, &icmpv6_protocol, st_src, st_dest,
89
 	if ( ( rc = tcpip_tx ( iobuf, &icmpv6_protocol, st_src, st_dest,
90
 			       netdev, &ndp->icmp.chksum ) ) != 0 ) {
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
 		return rc;
93
 		return rc;
94
 	}
94
 	}
95
 
95
 
205
 	/* Sanity check */
205
 	/* Sanity check */
206
 	if ( offsetof ( typeof ( *ll_addr_opt ),
206
 	if ( offsetof ( typeof ( *ll_addr_opt ),
207
 			ll_addr[ll_protocol->ll_addr_len] ) > len ) {
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
 		return -EINVAL;
211
 		return -EINVAL;
211
 	}
212
 	}
212
 
213
 
214
 	if ( ( rc = neighbour_define ( netdev, &ipv6_protocol,
215
 	if ( ( rc = neighbour_define ( netdev, &ipv6_protocol,
215
 				       &sin6_src->sin6_addr,
216
 				       &sin6_src->sin6_addr,
216
 				       ll_addr_opt->ll_addr ) ) != 0 ) {
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
 		       ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
220
 		       ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
220
 		       strerror ( rc ) );
221
 		       strerror ( rc ) );
221
 		return rc;
222
 		return rc;
260
 	/* Sanity check */
261
 	/* Sanity check */
261
 	if ( offsetof ( typeof ( *ll_addr_opt ),
262
 	if ( offsetof ( typeof ( *ll_addr_opt ),
262
 			ll_addr[ll_protocol->ll_addr_len] ) > len ) {
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
 		return -EINVAL;
267
 		return -EINVAL;
266
 	}
268
 	}
267
 
269
 
268
 	/* Update neighbour cache entry, if any */
270
 	/* Update neighbour cache entry, if any */
269
 	if ( ( rc = neighbour_update ( netdev, &ipv6_protocol, &neigh->target,
271
 	if ( ( rc = neighbour_update ( netdev, &ipv6_protocol, &neigh->target,
270
 				       ll_addr_opt->ll_addr ) ) != 0 ) {
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
 		       ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
275
 		       ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
274
 		       strerror ( rc ) );
276
 		       strerror ( rc ) );
275
 		return rc;
277
 		return rc;
300
 	/* Sanity check */
302
 	/* Sanity check */
301
 	if ( offsetof ( typeof ( *ll_addr_opt ),
303
 	if ( offsetof ( typeof ( *ll_addr_opt ),
302
 			ll_addr[ll_protocol->ll_addr_len] ) > len ) {
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
 		return -EINVAL;
307
 		return -EINVAL;
306
 	}
308
 	}
307
 
309
 
309
 	if ( ( rc = neighbour_define ( netdev, &ipv6_protocol,
311
 	if ( ( rc = neighbour_define ( netdev, &ipv6_protocol,
310
 				       &sin6_src->sin6_addr,
312
 				       &sin6_src->sin6_addr,
311
 				       ll_addr_opt->ll_addr ) ) != 0 ) {
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
 		       ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
316
 		       ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
315
 		       strerror ( rc ) );
317
 		       strerror ( rc ) );
316
 		return rc;
318
 		return rc;
337
 	struct ndp_router_advertisement_header *radv = &ndp->radv;
339
 	struct ndp_router_advertisement_header *radv = &ndp->radv;
338
 	struct ndp_prefix_information_option *prefix_opt = &option->prefix;
340
 	struct ndp_prefix_information_option *prefix_opt = &option->prefix;
339
 	struct in6_addr *router = &sin6_src->sin6_addr;
341
 	struct in6_addr *router = &sin6_src->sin6_addr;
342
+	struct in6_addr address;
343
+	int prefix_len;
340
 	int rc;
344
 	int rc;
341
 
345
 
342
 	/* Sanity check */
346
 	/* Sanity check */
343
 	if ( sizeof ( *prefix_opt ) > len ) {
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
 		return -EINVAL;
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
 	       inet6_ntoa ( &sin6_src->sin6_addr ) );
354
 	       inet6_ntoa ( &sin6_src->sin6_addr ) );
351
 	DBGC ( netdev, "for %s-link %sautonomous prefix %s/%d\n",
355
 	DBGC ( netdev, "for %s-link %sautonomous prefix %s/%d\n",
352
 	       ( ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) ? "on" : "off" ),
356
 	       ( ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) ? "on" : "off" ),
354
 	       inet6_ntoa ( &prefix_opt->prefix ),
358
 	       inet6_ntoa ( &prefix_opt->prefix ),
355
 	       prefix_opt->prefix_len );
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
 	/* Perform stateless address autoconfiguration, if applicable */
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
 			return rc;
396
 			return rc;
369
 		}
397
 		}
370
 	}
398
 	}
467
 
495
 
468
 	/* Sanity check */
496
 	/* Sanity check */
469
 	if ( len < offset ) {
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
 		return -EINVAL;
500
 		return -EINVAL;
473
 	}
501
 	}
474
 
502
 
482
 		     ( option->header.blocks == 0 ) ||
510
 		     ( option->header.blocks == 0 ) ||
483
 		     ( remaining < ( option->header.blocks *
511
 		     ( remaining < ( option->header.blocks *
484
 				     NDP_OPTION_BLKSZ ) ) ) {
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
 			DBGC_HDA ( netdev, 0, option, remaining );
515
 			DBGC_HDA ( netdev, 0, option, remaining );
487
 			return -EINVAL;
516
 			return -EINVAL;
488
 		}
517
 		}
715
 		stateful = ( flags & NDP_ROUTER_MANAGED );
744
 		stateful = ( flags & NDP_ROUTER_MANAGED );
716
 		if ( ( rc = start_dhcpv6 ( &ipv6conf->dhcp, netdev,
745
 		if ( ( rc = start_dhcpv6 ( &ipv6conf->dhcp, netdev,
717
 					   stateful ) ) != 0 ) {
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
 			ipv6conf_done ( ipv6conf, rc );
750
 			ipv6conf_done ( ipv6conf, rc );
722
 			return rc;
751
 			return rc;
723
 		}
752
 		}

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

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

Loading…
Cancel
Save