david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[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.
This commit is contained in:
Michael Brown 2009-01-21 03:40:39 +00:00
parent b4a95a8974
commit d230b53df2
7 changed files with 29 additions and 20 deletions

View File

@ -82,6 +82,7 @@ struct tcpip_net_protocol {
*
* @v iobuf I/O buffer
* @v tcpip_protocol Transport-layer protocol
* @v st_src Source address, or NULL to use default
* @v st_dest Destination address
* @v netdev Network device (or NULL to route automatically)
* @v trans_csum Transport-layer checksum to complete, or NULL
@ -91,6 +92,7 @@ struct tcpip_net_protocol {
*/
int ( * 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 );
@ -107,7 +109,8 @@ struct tcpip_net_protocol {
extern int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto,
struct sockaddr_tcpip *st_src,
struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum );
extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
struct sockaddr_tcpip *st_src,
struct sockaddr_tcpip *st_dest,
struct net_device *netdev,
uint16_t *trans_csum );

View File

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

View File

@ -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;
}

View File

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

View File

@ -491,7 +491,7 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
DBGC ( tcp, "\n" );
/* Transmit packet */
return tcpip_tx ( iobuf, &tcp_protocol, &tcp->peer, NULL,
return tcpip_tx ( iobuf, &tcp_protocol, NULL, &tcp->peer, NULL,
&tcphdr->csum );
}
@ -572,7 +572,7 @@ static int tcp_xmit_reset ( struct tcp_connection *tcp,
DBGC ( tcp, "\n" );
/* Transmit packet */
return tcpip_tx ( iobuf, &tcp_protocol, st_dest,
return tcpip_tx ( iobuf, &tcp_protocol, NULL, st_dest,
NULL, &tcphdr->csum );
}

View File

@ -64,14 +64,15 @@ int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto,
*
* @v iobuf I/O buffer
* @v tcpip_protocol Transport-layer protocol
* @v st_src Source address, or NULL to use route default
* @v st_dest Destination address
* @v netdev Network device to use if no route found, or NULL
* @v trans_csum Transport-layer checksum to complete, or NULL
* @ret rc Return status code
*/
int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
struct sockaddr_tcpip *st_dest, struct net_device *netdev,
uint16_t *trans_csum ) {
struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest,
struct net_device *netdev, uint16_t *trans_csum ) {
struct tcpip_net_protocol *tcpip_net;
/* 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,
tcpip_net < tcpip_net_protocols_end ; tcpip_net++ ) {
if ( tcpip_net->sa_family == st_dest->st_family ) {
DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
return tcpip_net->tx ( iobuf, tcpip_protocol, st_dest,
netdev, trans_csum );
return tcpip_net->tx ( iobuf, tcpip_protocol, st_src,
st_dest, netdev, trans_csum );
}
}

View File

@ -182,13 +182,13 @@ static void udp_close ( struct udp_connection *udp, int rc ) {
*
* @v udp UDP connection
* @v iobuf I/O buffer
* @v src_port Source port, or 0 to use default
* @v src Source address, or NULL to use default
* @v dest Destination address, or NULL to use default
* @v netdev Network device, or NULL to use default
* @ret rc Return status code
*/
static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
unsigned int src_port, struct sockaddr_tcpip *dest,
struct sockaddr_tcpip *src, struct sockaddr_tcpip *dest,
struct net_device *netdev ) {
struct udp_header *udphdr;
size_t len;
@ -201,8 +201,8 @@ static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
}
/* Fill in default values if not explicitly provided */
if ( ! src_port )
src_port = udp->local.st_port;
if ( ! src )
src = &udp->local;
if ( ! dest )
dest = &udp->peer;
@ -210,7 +210,7 @@ static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
udphdr = iob_push ( iobuf, sizeof ( *udphdr ) );
len = iob_len ( iobuf );
udphdr->dest = dest->st_port;
udphdr->src = src_port;
udphdr->src = src->st_port;
udphdr->len = htons ( len );
udphdr->chksum = 0;
udphdr->chksum = tcpip_chksum ( udphdr, len );
@ -221,7 +221,7 @@ static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
ntohs ( udphdr->len ) );
/* Send it to the next layer for processing */
if ( ( rc = tcpip_tx ( iobuf, &udp_protocol, dest, netdev,
if ( ( rc = tcpip_tx ( iobuf, &udp_protocol, src, dest, netdev,
&udphdr->chksum ) ) != 0 ) {
DBGC ( udp, "UDP %p could not transmit packet: %s\n",
udp, strerror ( rc ) );
@ -399,22 +399,19 @@ static int udp_xfer_deliver_iob ( struct xfer_interface *xfer,
struct xfer_metadata *meta ) {
struct udp_connection *udp =
container_of ( xfer, struct udp_connection, xfer );
struct sockaddr_tcpip *src;
struct sockaddr_tcpip *src = NULL;
struct sockaddr_tcpip *dest = NULL;
struct net_device *netdev = NULL;
unsigned int src_port = 0;
/* Apply xfer metadata */
if ( meta ) {
src = ( struct sockaddr_tcpip * ) meta->src;
if ( src )
src_port = src->st_port;
dest = ( struct sockaddr_tcpip * ) meta->dest;
netdev = meta->netdev;
}
/* Transmit data, if possible */
udp_tx ( udp, iobuf, src_port, dest, netdev );
udp_tx ( udp, iobuf, src, dest, netdev );
return 0;
}