Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[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.
  • Loading branch information
Michael Brown committed Jan 21, 2009
1 parent b4a95a8 commit d230b53
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 20 deletions.
5 changes: 4 additions & 1 deletion src/include/gpxe/tcpip.h
Expand Up @@ -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
Expand All @@ -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 );
Expand All @@ -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 );
Expand Down
2 changes: 1 addition & 1 deletion src/net/icmpv6.c
Expand Up @@ -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 );
}

Expand Down
9 changes: 8 additions & 1 deletion src/net/ipv4.c
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions src/net/ipv6.c
Expand Up @@ -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 ) {
Expand Down
4 changes: 2 additions & 2 deletions src/net/tcp.c
Expand Up @@ -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 );
}

Expand Down Expand Up @@ -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 );
}

Expand Down
9 changes: 5 additions & 4 deletions src/net/tcpip.c
Expand Up @@ -64,23 +64,24 @@ 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 */
for ( tcpip_net = tcpip_net_protocols ;
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 );
}
}

Expand Down
19 changes: 8 additions & 11 deletions src/net/udp.c
Expand Up @@ -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;
Expand All @@ -201,16 +201,16 @@ 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;

/* Add the UDP header */
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 );
Expand All @@ -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 ) );
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit d230b53

Please sign in to comment.