Browse Source

[ipv4] Allow IPv4 socket addresses to include a scope ID

Extend the IPv6 concept of "scope ID" (indicating the network device
index) to IPv4 socket addresses, so that IPv4 multicast transmissions
may specify the transmitting network device.

The scope ID is not (currently) exposed via the string representation
of the socket address, since IPv4 does not use the IPv6 concept of
link-local addresses (which could legitimately be specified in a URI).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
2bcf13f13a
3 changed files with 50 additions and 15 deletions
  1. 9
    2
      src/include/ipxe/in.h
  2. 8
    1
      src/include/ipxe/tcpip.h
  3. 33
    12
      src/net/ipv4.c

+ 9
- 2
src/include/ipxe/in.h View File

85
 	uint16_t sin_flags;
85
 	uint16_t sin_flags;
86
 	/** TCP/IP port (part of struct @c sockaddr_tcpip) */
86
 	/** TCP/IP port (part of struct @c sockaddr_tcpip) */
87
 	uint16_t sin_port;
87
 	uint16_t sin_port;
88
+	/** Scope ID (part of struct @c sockaddr_tcpip)
89
+	 *
90
+	 * For multicast addresses, this is the network device index.
91
+	 */
92
+        uint16_t sin_scope_id;
88
 	/** IPv4 address */
93
 	/** IPv4 address */
89
 	struct in_addr sin_addr;
94
 	struct in_addr sin_addr;
90
 	/** Padding
95
 	/** Padding
96
 		  ( sizeof ( sa_family_t ) /* sin_family */ +
101
 		  ( sizeof ( sa_family_t ) /* sin_family */ +
97
 		    sizeof ( uint16_t ) /* sin_flags */ +
102
 		    sizeof ( uint16_t ) /* sin_flags */ +
98
 		    sizeof ( uint16_t ) /* sin_port */ +
103
 		    sizeof ( uint16_t ) /* sin_port */ +
104
+		    sizeof ( uint16_t ) /* sin_scope_id */ +
99
 		    sizeof ( struct in_addr ) /* sin_addr */ ) ];
105
 		    sizeof ( struct in_addr ) /* sin_addr */ ) ];
100
 } __attribute__ (( packed, may_alias ));
106
 } __attribute__ (( packed, may_alias ));
101
 
107
 
112
 	uint16_t sin6_flags;
118
 	uint16_t sin6_flags;
113
 	/** TCP/IP port (part of struct @c sockaddr_tcpip) */
119
 	/** TCP/IP port (part of struct @c sockaddr_tcpip) */
114
 	uint16_t sin6_port;
120
 	uint16_t sin6_port;
115
-	/** Scope ID
121
+	/** Scope ID (part of struct @c sockaddr_tcpip)
116
 	 *
122
 	 *
117
-	 * For link-local addresses, this is the network device index.
123
+	 * For link-local or multicast addresses, this is the network
124
+	 * device index.
118
 	 */
125
 	 */
119
         uint16_t sin6_scope_id;
126
         uint16_t sin6_scope_id;
120
 	/** IPv6 address */
127
 	/** IPv6 address */

+ 8
- 1
src/include/ipxe/tcpip.h View File

48
 	uint16_t st_flags;
48
 	uint16_t st_flags;
49
 	/** TCP/IP port */
49
 	/** TCP/IP port */
50
 	uint16_t st_port;
50
 	uint16_t st_port;
51
+	/** Scope ID
52
+	 *
53
+	 * For link-local or multicast addresses, this is the network
54
+	 * device index.
55
+	 */
56
+        uint16_t st_scope_id;
51
 	/** Padding
57
 	/** Padding
52
 	 *
58
 	 *
53
 	 * This ensures that a struct @c sockaddr_tcpip is large
59
 	 * This ensures that a struct @c sockaddr_tcpip is large
57
 	char pad[ sizeof ( struct sockaddr ) -
63
 	char pad[ sizeof ( struct sockaddr ) -
58
 		  ( sizeof ( sa_family_t ) /* st_family */ +
64
 		  ( sizeof ( sa_family_t ) /* st_family */ +
59
 		    sizeof ( uint16_t ) /* st_flags */ +
65
 		    sizeof ( uint16_t ) /* st_flags */ +
60
-		    sizeof ( uint16_t ) /* st_port */ ) ];
66
+		    sizeof ( uint16_t ) /* st_port */ +
67
+		    sizeof ( uint16_t ) /* st_scope_id */ ) ];
61
 } __attribute__ (( packed, may_alias ));
68
 } __attribute__ (( packed, may_alias ));
62
 
69
 
63
 /** 
70
 /** 

+ 33
- 12
src/net/ipv4.c View File

139
 /**
139
 /**
140
  * Perform IPv4 routing
140
  * Perform IPv4 routing
141
  *
141
  *
142
+ * @v scope_id		Destination address scope ID
142
  * @v dest		Final destination address
143
  * @v dest		Final destination address
143
  * @ret dest		Next hop destination address
144
  * @ret dest		Next hop destination address
144
  * @ret miniroute	Routing table entry to use, or NULL if no route
145
  * @ret miniroute	Routing table entry to use, or NULL if no route
146
  * If the route requires use of a gateway, the next hop destination
147
  * If the route requires use of a gateway, the next hop destination
147
  * address will be overwritten with the gateway address.
148
  * address will be overwritten with the gateway address.
148
  */
149
  */
149
-static struct ipv4_miniroute * ipv4_route ( struct in_addr *dest ) {
150
+static struct ipv4_miniroute * ipv4_route ( unsigned int scope_id,
151
+					    struct in_addr *dest ) {
150
 	struct ipv4_miniroute *miniroute;
152
 	struct ipv4_miniroute *miniroute;
151
-	int local;
152
-	int has_gw;
153
 
153
 
154
 	/* Find first usable route in routing table */
154
 	/* Find first usable route in routing table */
155
 	list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
155
 	list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
156
+
157
+		/* Skip closed network devices */
156
 		if ( ! netdev_is_open ( miniroute->netdev ) )
158
 		if ( ! netdev_is_open ( miniroute->netdev ) )
157
 			continue;
159
 			continue;
158
-		local = ( ( ( dest->s_addr ^ miniroute->address.s_addr )
159
-			    & miniroute->netmask.s_addr ) == 0 );
160
-		has_gw = ( miniroute->gateway.s_addr );
161
-		if ( local || has_gw ) {
162
-			if ( ! local )
160
+
161
+		if ( IN_IS_MULTICAST ( dest->s_addr ) ) {
162
+
163
+			/* If destination is non-global, and the scope ID
164
+			 * matches this network device, then use this route.
165
+			 */
166
+			if ( miniroute->netdev->index == scope_id )
167
+				return miniroute;
168
+
169
+		} else {
170
+
171
+			/* If destination is an on-link global
172
+			 * address, then use this route.
173
+			 */
174
+			if ( ( ( dest->s_addr ^ miniroute->address.s_addr )
175
+			       & miniroute->netmask.s_addr ) == 0 )
176
+				return miniroute;
177
+
178
+			/* If destination is an off-link global
179
+			 * address, and we have a default gateway,
180
+			 * then use this route.
181
+			 */
182
+			if ( miniroute->gateway.s_addr ) {
163
 				*dest = miniroute->gateway;
183
 				*dest = miniroute->gateway;
164
-			return miniroute;
184
+				return miniroute;
185
+			}
165
 		}
186
 		}
166
 	}
187
 	}
167
 
188
 
180
 	struct ipv4_miniroute *miniroute;
201
 	struct ipv4_miniroute *miniroute;
181
 
202
 
182
 	/* Find routing table entry */
203
 	/* Find routing table entry */
183
-	miniroute = ipv4_route ( &dest );
204
+	miniroute = ipv4_route ( sin_dest->sin_scope_id, &dest );
184
 	if ( ! miniroute )
205
 	if ( ! miniroute )
185
 		return NULL;
206
 		return NULL;
186
 
207
 
314
 	if ( sin_src )
335
 	if ( sin_src )
315
 		iphdr->src = sin_src->sin_addr;
336
 		iphdr->src = sin_src->sin_addr;
316
 	if ( ( next_hop.s_addr != INADDR_BROADCAST ) &&
337
 	if ( ( next_hop.s_addr != INADDR_BROADCAST ) &&
317
-	     ( ! IN_IS_MULTICAST ( next_hop.s_addr ) ) &&
318
-	     ( ( miniroute = ipv4_route ( &next_hop ) ) != NULL ) ) {
338
+	     ( ( miniroute = ipv4_route ( sin_dest->sin_scope_id,
339
+					  &next_hop ) ) != NULL ) ) {
319
 		iphdr->src = miniroute->address;
340
 		iphdr->src = miniroute->address;
320
 		netmask = miniroute->netmask;
341
 		netmask = miniroute->netmask;
321
 		netdev = miniroute->netdev;
342
 		netdev = miniroute->netdev;

Loading…
Cancel
Save