aboutsummaryrefslogtreecommitdiff
path: root/src/net/ipv4.c
diff options
context:
space:
mode:
authorMichael Brown <mcb30@etherboot.org>2009-01-21 03:40:39 +0000
committerMichael Brown <mcb30@etherboot.org>2009-01-21 03:40:39 +0000
commitd230b53df2f44da477742094e5bbcc1b1520347c (patch)
tree4d0c8e9591509360aa7a7b1135ae39d6eab320ee /src/net/ipv4.c
parentb4a95a8974dd073b580d6a23383fa94b3d59d989 (diff)
downloadipxe-d230b53df2f44da477742094e5bbcc1b1520347c.zip
ipxe-d230b53df2f44da477742094e5bbcc1b1520347c.tar.gz
ipxe-d230b53df2f44da477742094e5bbcc1b1520347c.tar.bz2
[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.
Diffstat (limited to 'src/net/ipv4.c')
-rw-r--r--src/net/ipv4.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/src/net/ipv4.c b/src/net/ipv4.c
index 63dcca2..335048c 100644
--- a/src/net/ipv4.c
+++ b/src/net/ipv4.c
@@ -286,6 +286,7 @@ static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
*
* @v iobuf I/O buffer
* @v tcpip Transport-layer protocol
+ * @v st_src Source network-layer address
* @v st_dest Destination network-layer address
* @v netdev Network device to use if no route found, or NULL
* @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,
*/
static int ipv4_tx ( struct io_buffer *iobuf,
struct tcpip_protocol *tcpip_protocol,
+ struct sockaddr_tcpip *st_src,
struct sockaddr_tcpip *st_dest,
struct net_device *netdev,
uint16_t *trans_csum ) {
struct iphdr *iphdr = iob_push ( iobuf, sizeof ( *iphdr ) );
+ struct sockaddr_in *sin_src = ( ( struct sockaddr_in * ) st_src );
struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
struct ipv4_miniroute *miniroute;
struct in_addr next_hop;
@@ -317,7 +320,11 @@ static int ipv4_tx ( struct io_buffer *iobuf,
/* Use routing table to identify next hop and transmitting netdev */
next_hop = iphdr->dest;
- if ( ( miniroute = ipv4_route ( &next_hop ) ) ) {
+ if ( sin_src )
+ iphdr->src = sin_src->sin_addr;
+ if ( ( next_hop.s_addr != INADDR_BROADCAST ) &&
+ ( ! IN_MULTICAST ( ntohl ( next_hop.s_addr ) ) ) &&
+ ( ( miniroute = ipv4_route ( &next_hop ) ) != NULL ) ) {
iphdr->src = miniroute->address;
netdev = miniroute->netdev;
}