Преглед изворни кода

[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 година
родитељ
комит
2bcf13f13a
3 измењених фајлова са 50 додато и 15 уклоњено
  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 Прегледај датотеку

@@ -85,6 +85,11 @@ struct sockaddr_in {
85 85
 	uint16_t sin_flags;
86 86
 	/** TCP/IP port (part of struct @c sockaddr_tcpip) */
87 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 93
 	/** IPv4 address */
89 94
 	struct in_addr sin_addr;
90 95
 	/** Padding
@@ -96,6 +101,7 @@ struct sockaddr_in {
96 101
 		  ( sizeof ( sa_family_t ) /* sin_family */ +
97 102
 		    sizeof ( uint16_t ) /* sin_flags */ +
98 103
 		    sizeof ( uint16_t ) /* sin_port */ +
104
+		    sizeof ( uint16_t ) /* sin_scope_id */ +
99 105
 		    sizeof ( struct in_addr ) /* sin_addr */ ) ];
100 106
 } __attribute__ (( packed, may_alias ));
101 107
 
@@ -112,9 +118,10 @@ struct sockaddr_in6 {
112 118
 	uint16_t sin6_flags;
113 119
 	/** TCP/IP port (part of struct @c sockaddr_tcpip) */
114 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 126
         uint16_t sin6_scope_id;
120 127
 	/** IPv6 address */

+ 8
- 1
src/include/ipxe/tcpip.h Прегледај датотеку

@@ -48,6 +48,12 @@ struct sockaddr_tcpip {
48 48
 	uint16_t st_flags;
49 49
 	/** TCP/IP port */
50 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 57
 	/** Padding
52 58
 	 *
53 59
 	 * This ensures that a struct @c sockaddr_tcpip is large
@@ -57,7 +63,8 @@ struct sockaddr_tcpip {
57 63
 	char pad[ sizeof ( struct sockaddr ) -
58 64
 		  ( sizeof ( sa_family_t ) /* st_family */ +
59 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 68
 } __attribute__ (( packed, may_alias ));
62 69
 
63 70
 /** 

+ 33
- 12
src/net/ipv4.c Прегледај датотеку

@@ -139,6 +139,7 @@ static void del_ipv4_miniroute ( struct ipv4_miniroute *miniroute ) {
139 139
 /**
140 140
  * Perform IPv4 routing
141 141
  *
142
+ * @v scope_id		Destination address scope ID
142 143
  * @v dest		Final destination address
143 144
  * @ret dest		Next hop destination address
144 145
  * @ret miniroute	Routing table entry to use, or NULL if no route
@@ -146,22 +147,42 @@ static void del_ipv4_miniroute ( struct ipv4_miniroute *miniroute ) {
146 147
  * If the route requires use of a gateway, the next hop destination
147 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 152
 	struct ipv4_miniroute *miniroute;
151
-	int local;
152
-	int has_gw;
153 153
 
154 154
 	/* Find first usable route in routing table */
155 155
 	list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
156
+
157
+		/* Skip closed network devices */
156 158
 		if ( ! netdev_is_open ( miniroute->netdev ) )
157 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 183
 				*dest = miniroute->gateway;
164
-			return miniroute;
184
+				return miniroute;
185
+			}
165 186
 		}
166 187
 	}
167 188
 
@@ -180,7 +201,7 @@ static struct net_device * ipv4_netdev ( struct sockaddr_tcpip *st_dest ) {
180 201
 	struct ipv4_miniroute *miniroute;
181 202
 
182 203
 	/* Find routing table entry */
183
-	miniroute = ipv4_route ( &dest );
204
+	miniroute = ipv4_route ( sin_dest->sin_scope_id, &dest );
184 205
 	if ( ! miniroute )
185 206
 		return NULL;
186 207
 
@@ -314,8 +335,8 @@ static int ipv4_tx ( struct io_buffer *iobuf,
314 335
 	if ( sin_src )
315 336
 		iphdr->src = sin_src->sin_addr;
316 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 340
 		iphdr->src = miniroute->address;
320 341
 		netmask = miniroute->netmask;
321 342
 		netdev = miniroute->netdev;

Loading…
Откажи
Сачувај