Browse 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 16 years ago
parent
commit
d230b53df2
7 changed files with 29 additions and 20 deletions
  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 View File

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

+ 1
- 1
src/net/icmpv6.c View File

60
 	st_dest.sin6.sin6_addr.in6_u.u6_addr8[13] = 0xff;
60
 	st_dest.sin6.sin6_addr.in6_u.u6_addr8[13] = 0xff;
61
 	
61
 	
62
 	/* Send packet over IP6 */
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
 			  NULL, &nsolicit->csum );
64
 			  NULL, &nsolicit->csum );
65
 }
65
 }
66
 
66
 

+ 8
- 1
src/net/ipv4.c View File

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

+ 1
- 0
src/net/ipv6.c View File

176
  */
176
  */
177
 static int ipv6_tx ( struct io_buffer *iobuf,
177
 static int ipv6_tx ( struct io_buffer *iobuf,
178
 		     struct tcpip_protocol *tcpip,
178
 		     struct tcpip_protocol *tcpip,
179
+		     struct sockaddr_tcpip *st_src __unused,
179
 		     struct sockaddr_tcpip *st_dest,
180
 		     struct sockaddr_tcpip *st_dest,
180
 		     struct net_device *netdev,
181
 		     struct net_device *netdev,
181
 		     uint16_t *trans_csum ) {
182
 		     uint16_t *trans_csum ) {

+ 2
- 2
src/net/tcp.c View File

491
 	DBGC ( tcp, "\n" );
491
 	DBGC ( tcp, "\n" );
492
 
492
 
493
 	/* Transmit packet */
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
 			  &tcphdr->csum );
495
 			  &tcphdr->csum );
496
 }
496
 }
497
 
497
 
572
 	DBGC ( tcp, "\n" );
572
 	DBGC ( tcp, "\n" );
573
 
573
 
574
 	/* Transmit packet */
574
 	/* Transmit packet */
575
-	return tcpip_tx ( iobuf, &tcp_protocol, st_dest,
575
+	return tcpip_tx ( iobuf, &tcp_protocol, NULL, st_dest,
576
 			  NULL, &tcphdr->csum );
576
 			  NULL, &tcphdr->csum );
577
 }
577
 }
578
 
578
 

+ 5
- 4
src/net/tcpip.c View File

64
  *
64
  *
65
  * @v iobuf		I/O buffer
65
  * @v iobuf		I/O buffer
66
  * @v tcpip_protocol	Transport-layer protocol
66
  * @v tcpip_protocol	Transport-layer protocol
67
+ * @v st_src		Source address, or NULL to use route default
67
  * @v st_dest		Destination address
68
  * @v st_dest		Destination address
68
  * @v netdev		Network device to use if no route found, or NULL
69
  * @v netdev		Network device to use if no route found, or NULL
69
  * @v trans_csum	Transport-layer checksum to complete, or NULL
70
  * @v trans_csum	Transport-layer checksum to complete, or NULL
70
  * @ret rc		Return status code
71
  * @ret rc		Return status code
71
  */
72
  */
72
 int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
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
 	struct tcpip_net_protocol *tcpip_net;
76
 	struct tcpip_net_protocol *tcpip_net;
76
 
77
 
77
 	/* Hand off packet to the appropriate network-layer protocol */
78
 	/* Hand off packet to the appropriate network-layer protocol */
79
 	      tcpip_net < tcpip_net_protocols_end ; tcpip_net++ ) {
80
 	      tcpip_net < tcpip_net_protocols_end ; tcpip_net++ ) {
80
 		if ( tcpip_net->sa_family == st_dest->st_family ) {
81
 		if ( tcpip_net->sa_family == st_dest->st_family ) {
81
 			DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
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 View File

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

Loading…
Cancel
Save