Parcourir la source

[tcpip] Allow for transmission to multicast IPv4 addresses

When sending to a multicast address, it may be necessary to specify
the source address explicitly, since the multicast destination address
does not provide enough information to deduce the source address via
the miniroute table.

Allow the source address specified via the data-xfer metadata to be
passed down through the TCP/IP stack to the IPv4 layer, which can use
it as a default source address.
tags/v0.9.7
Michael Brown il y a 16 ans
Parent
révision
d230b53df2
7 fichiers modifiés avec 29 ajouts et 20 suppressions
  1. 4
    1
      src/include/gpxe/tcpip.h
  2. 1
    1
      src/net/icmpv6.c
  3. 8
    1
      src/net/ipv4.c
  4. 1
    0
      src/net/ipv6.c
  5. 2
    2
      src/net/tcp.c
  6. 5
    4
      src/net/tcpip.c
  7. 8
    11
      src/net/udp.c

+ 4
- 1
src/include/gpxe/tcpip.h Voir le fichier

@@ -82,6 +82,7 @@ struct tcpip_net_protocol {
82 82
 	 *
83 83
 	 * @v iobuf		I/O buffer
84 84
 	 * @v tcpip_protocol	Transport-layer protocol
85
+	 * @v st_src		Source address, or NULL to use default
85 86
 	 * @v st_dest		Destination address
86 87
 	 * @v netdev		Network device (or NULL to route automatically)
87 88
 	 * @v trans_csum	Transport-layer checksum to complete, or NULL
@@ -91,6 +92,7 @@ struct tcpip_net_protocol {
91 92
 	 */
92 93
 	int ( * tx ) ( struct io_buffer *iobuf,
93 94
 		       struct tcpip_protocol *tcpip_protocol,
95
+		       struct sockaddr_tcpip *st_src,
94 96
 		       struct sockaddr_tcpip *st_dest,
95 97
 		       struct net_device *netdev,
96 98
 		       uint16_t *trans_csum );
@@ -107,7 +109,8 @@ struct tcpip_net_protocol {
107 109
 extern int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto,
108 110
 		      struct sockaddr_tcpip *st_src,
109 111
 		      struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum );
110
-extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip, 
112
+extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
113
+		      struct sockaddr_tcpip *st_src,
111 114
 		      struct sockaddr_tcpip *st_dest,
112 115
 		      struct net_device *netdev,
113 116
 		      uint16_t *trans_csum );

+ 1
- 1
src/net/icmpv6.c Voir le fichier

@@ -60,7 +60,7 @@ int icmp6_send_solicit ( struct net_device *netdev, struct in6_addr *src __unuse
60 60
 	st_dest.sin6.sin6_addr.in6_u.u6_addr8[13] = 0xff;
61 61
 	
62 62
 	/* Send packet over IP6 */
63
-	return tcpip_tx ( iobuf, &icmp6_protocol, &st_dest.st,
63
+	return tcpip_tx ( iobuf, &icmp6_protocol, NULL, &st_dest.st,
64 64
 			  NULL, &nsolicit->csum );
65 65
 }
66 66
 

+ 8
- 1
src/net/ipv4.c Voir le fichier

@@ -286,6 +286,7 @@ static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
286 286
  *
287 287
  * @v iobuf		I/O buffer
288 288
  * @v tcpip		Transport-layer protocol
289
+ * @v st_src		Source network-layer address
289 290
  * @v st_dest		Destination network-layer address
290 291
  * @v netdev		Network device to use if no route found, or NULL
291 292
  * @v trans_csum	Transport-layer checksum to complete, or NULL
@@ -295,10 +296,12 @@ static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
295 296
  */
296 297
 static int ipv4_tx ( struct io_buffer *iobuf,
297 298
 		     struct tcpip_protocol *tcpip_protocol,
299
+		     struct sockaddr_tcpip *st_src,
298 300
 		     struct sockaddr_tcpip *st_dest,
299 301
 		     struct net_device *netdev,
300 302
 		     uint16_t *trans_csum ) {
301 303
 	struct iphdr *iphdr = iob_push ( iobuf, sizeof ( *iphdr ) );
304
+	struct sockaddr_in *sin_src = ( ( struct sockaddr_in * ) st_src );
302 305
 	struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
303 306
 	struct ipv4_miniroute *miniroute;
304 307
 	struct in_addr next_hop;
@@ -317,7 +320,11 @@ static int ipv4_tx ( struct io_buffer *iobuf,
317 320
 
318 321
 	/* Use routing table to identify next hop and transmitting netdev */
319 322
 	next_hop = iphdr->dest;
320
-	if ( ( miniroute = ipv4_route ( &next_hop ) ) ) {
323
+	if ( sin_src )
324
+		iphdr->src = sin_src->sin_addr;
325
+	if ( ( next_hop.s_addr != INADDR_BROADCAST ) &&
326
+	     ( ! IN_MULTICAST ( ntohl ( next_hop.s_addr ) ) ) &&
327
+	     ( ( miniroute = ipv4_route ( &next_hop ) ) != NULL ) ) {
321 328
 		iphdr->src = miniroute->address;
322 329
 		netdev = miniroute->netdev;
323 330
 	}

+ 1
- 0
src/net/ipv6.c Voir le fichier

@@ -176,6 +176,7 @@ void ipv6_dump ( struct ip6_header *ip6hdr ) {
176 176
  */
177 177
 static int ipv6_tx ( struct io_buffer *iobuf,
178 178
 		     struct tcpip_protocol *tcpip,
179
+		     struct sockaddr_tcpip *st_src __unused,
179 180
 		     struct sockaddr_tcpip *st_dest,
180 181
 		     struct net_device *netdev,
181 182
 		     uint16_t *trans_csum ) {

+ 2
- 2
src/net/tcp.c Voir le fichier

@@ -491,7 +491,7 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
491 491
 	DBGC ( tcp, "\n" );
492 492
 
493 493
 	/* Transmit packet */
494
-	return tcpip_tx ( iobuf, &tcp_protocol, &tcp->peer, NULL,
494
+	return tcpip_tx ( iobuf, &tcp_protocol, NULL, &tcp->peer, NULL,
495 495
 			  &tcphdr->csum );
496 496
 }
497 497
 
@@ -572,7 +572,7 @@ static int tcp_xmit_reset ( struct tcp_connection *tcp,
572 572
 	DBGC ( tcp, "\n" );
573 573
 
574 574
 	/* Transmit packet */
575
-	return tcpip_tx ( iobuf, &tcp_protocol, st_dest,
575
+	return tcpip_tx ( iobuf, &tcp_protocol, NULL, st_dest,
576 576
 			  NULL, &tcphdr->csum );
577 577
 }
578 578
 

+ 5
- 4
src/net/tcpip.c Voir le fichier

@@ -64,14 +64,15 @@ int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto,
64 64
  *
65 65
  * @v iobuf		I/O buffer
66 66
  * @v tcpip_protocol	Transport-layer protocol
67
+ * @v st_src		Source address, or NULL to use route default
67 68
  * @v st_dest		Destination address
68 69
  * @v netdev		Network device to use if no route found, or NULL
69 70
  * @v trans_csum	Transport-layer checksum to complete, or NULL
70 71
  * @ret rc		Return status code
71 72
  */
72 73
 int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
73
-	       struct sockaddr_tcpip *st_dest, struct net_device *netdev,
74
-	       uint16_t *trans_csum ) {
74
+	       struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest,
75
+	       struct net_device *netdev, uint16_t *trans_csum ) {
75 76
 	struct tcpip_net_protocol *tcpip_net;
76 77
 
77 78
 	/* Hand off packet to the appropriate network-layer protocol */
@@ -79,8 +80,8 @@ int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
79 80
 	      tcpip_net < tcpip_net_protocols_end ; tcpip_net++ ) {
80 81
 		if ( tcpip_net->sa_family == st_dest->st_family ) {
81 82
 			DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
82
-			return tcpip_net->tx ( iobuf, tcpip_protocol, st_dest,
83
-					       netdev, trans_csum );
83
+			return tcpip_net->tx ( iobuf, tcpip_protocol, st_src,
84
+					       st_dest, netdev, trans_csum );
84 85
 		}
85 86
 	}
86 87
 	

+ 8
- 11
src/net/udp.c Voir le fichier

@@ -182,13 +182,13 @@ static void udp_close ( struct udp_connection *udp, int rc ) {
182 182
  *
183 183
  * @v udp		UDP connection
184 184
  * @v iobuf		I/O buffer
185
- * @v src_port		Source port, or 0 to use default
185
+ * @v src		Source address, or NULL to use default
186 186
  * @v dest		Destination address, or NULL to use default
187 187
  * @v netdev		Network device, or NULL to use default
188 188
  * @ret rc		Return status code
189 189
  */
190 190
 static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
191
-		    unsigned int src_port, struct sockaddr_tcpip *dest,
191
+		    struct sockaddr_tcpip *src, struct sockaddr_tcpip *dest,
192 192
 		    struct net_device *netdev ) {
193 193
        	struct udp_header *udphdr;
194 194
 	size_t len;
@@ -201,8 +201,8 @@ static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
201 201
 	}
202 202
 
203 203
 	/* Fill in default values if not explicitly provided */
204
-	if ( ! src_port )
205
-		src_port = udp->local.st_port;
204
+	if ( ! src )
205
+		src = &udp->local;
206 206
 	if ( ! dest )
207 207
 		dest = &udp->peer;
208 208
 
@@ -210,7 +210,7 @@ static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
210 210
 	udphdr = iob_push ( iobuf, sizeof ( *udphdr ) );
211 211
 	len = iob_len ( iobuf );
212 212
 	udphdr->dest = dest->st_port;
213
-	udphdr->src = src_port;
213
+	udphdr->src = src->st_port;
214 214
 	udphdr->len = htons ( len );
215 215
 	udphdr->chksum = 0;
216 216
 	udphdr->chksum = tcpip_chksum ( udphdr, len );
@@ -221,7 +221,7 @@ static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
221 221
 	       ntohs ( udphdr->len ) );
222 222
 
223 223
 	/* Send it to the next layer for processing */
224
-	if ( ( rc = tcpip_tx ( iobuf, &udp_protocol, dest, netdev,
224
+	if ( ( rc = tcpip_tx ( iobuf, &udp_protocol, src, dest, netdev,
225 225
 			       &udphdr->chksum ) ) != 0 ) {
226 226
 		DBGC ( udp, "UDP %p could not transmit packet: %s\n",
227 227
 		       udp, strerror ( rc ) );
@@ -399,22 +399,19 @@ static int udp_xfer_deliver_iob ( struct xfer_interface *xfer,
399 399
 				  struct xfer_metadata *meta ) {
400 400
 	struct udp_connection *udp =
401 401
 		container_of ( xfer, struct udp_connection, xfer );
402
-	struct sockaddr_tcpip *src;
402
+	struct sockaddr_tcpip *src = NULL;
403 403
 	struct sockaddr_tcpip *dest = NULL;
404 404
 	struct net_device *netdev = NULL;
405
-	unsigned int src_port = 0;
406 405
 
407 406
 	/* Apply xfer metadata */
408 407
 	if ( meta ) {
409 408
 		src = ( struct sockaddr_tcpip * ) meta->src;
410
-		if ( src )
411
-			src_port = src->st_port;
412 409
 		dest = ( struct sockaddr_tcpip * ) meta->dest;
413 410
 		netdev = meta->netdev;
414 411
 	}
415 412
 
416 413
 	/* Transmit data, if possible */
417
-	udp_tx ( udp, iobuf, src_port, dest, netdev );
414
+	udp_tx ( udp, iobuf, src, dest, netdev );
418 415
 
419 416
 	return 0;
420 417
 }

Chargement…
Annuler
Enregistrer