mirror of https://github.com/ipxe/ipxe.git
Allow an explicit network device to be specified for IP-layer
transmissions.pull/1/head
parent
9869659895
commit
f008b77ba2
|
@ -13,6 +13,7 @@
|
||||||
#include <gpxe/tables.h>
|
#include <gpxe/tables.h>
|
||||||
|
|
||||||
struct pk_buff;
|
struct pk_buff;
|
||||||
|
struct net_device;
|
||||||
|
|
||||||
/** Empty checksum value
|
/** Empty checksum value
|
||||||
*
|
*
|
||||||
|
@ -84,6 +85,7 @@ struct tcpip_net_protocol {
|
||||||
* @v pkb Packet buffer
|
* @v pkb Packet buffer
|
||||||
* @v tcpip_protocol Transport-layer protocol
|
* @v tcpip_protocol Transport-layer protocol
|
||||||
* @v st_dest Destination address
|
* @v st_dest Destination address
|
||||||
|
* @v netdev Network device (or NULL to route automatically)
|
||||||
* @v trans_csum Transport-layer checksum to complete, or NULL
|
* @v trans_csum Transport-layer checksum to complete, or NULL
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*
|
*
|
||||||
|
@ -91,7 +93,9 @@ struct tcpip_net_protocol {
|
||||||
*/
|
*/
|
||||||
int ( * tx ) ( struct pk_buff *pkb,
|
int ( * tx ) ( struct pk_buff *pkb,
|
||||||
struct tcpip_protocol *tcpip_protocol,
|
struct tcpip_protocol *tcpip_protocol,
|
||||||
struct sockaddr_tcpip *st_dest, uint16_t *trans_csum );
|
struct sockaddr_tcpip *st_dest,
|
||||||
|
struct net_device *netdev,
|
||||||
|
uint16_t *trans_csum );
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Declare a TCP/IP transport-layer protocol */
|
/** Declare a TCP/IP transport-layer protocol */
|
||||||
|
@ -104,7 +108,9 @@ extern int tcpip_rx ( struct pk_buff *pkb, uint8_t tcpip_proto,
|
||||||
struct sockaddr_tcpip *st_src,
|
struct sockaddr_tcpip *st_src,
|
||||||
struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum );
|
struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum );
|
||||||
extern int tcpip_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
|
extern int tcpip_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
|
||||||
struct sockaddr_tcpip *st_dest, uint16_t *trans_csum );
|
struct sockaddr_tcpip *st_dest,
|
||||||
|
struct net_device *netdev,
|
||||||
|
uint16_t *trans_csum );
|
||||||
extern uint16_t tcpip_continue_chksum ( uint16_t partial,
|
extern uint16_t tcpip_continue_chksum ( uint16_t partial,
|
||||||
const void *data, size_t len );
|
const void *data, size_t len );
|
||||||
extern uint16_t tcpip_chksum ( const void *data, size_t len );
|
extern uint16_t tcpip_chksum ( const void *data, size_t len );
|
||||||
|
|
|
@ -60,7 +60,8 @@ int icmp6_send_solicit ( struct net_device *netdev, struct in6_addr *src __unuse
|
||||||
st_dest.sin6.sin6_addr.in6_u.u6_addr8[13] = 0xff;
|
st_dest.sin6.sin6_addr.in6_u.u6_addr8[13] = 0xff;
|
||||||
|
|
||||||
/* Send packet over IP6 */
|
/* Send packet over IP6 */
|
||||||
return tcpip_tx ( pkb, &icmp6_protocol, &st_dest.st, &nsolicit->csum );
|
return tcpip_tx ( pkb, &icmp6_protocol, &st_dest.st,
|
||||||
|
NULL, &nsolicit->csum );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -372,6 +372,7 @@ static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
|
||||||
* @v pkb Packet buffer
|
* @v pkb Packet buffer
|
||||||
* @v tcpip Transport-layer protocol
|
* @v tcpip Transport-layer protocol
|
||||||
* @v st_dest Destination network-layer address
|
* @v st_dest Destination network-layer address
|
||||||
|
* @v netdev Network device (or NULL to route automatically)
|
||||||
* @v trans_csum Transport-layer checksum to complete, or NULL
|
* @v trans_csum Transport-layer checksum to complete, or NULL
|
||||||
* @ret rc Status
|
* @ret rc Status
|
||||||
*
|
*
|
||||||
|
@ -379,7 +380,9 @@ static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
|
||||||
*/
|
*/
|
||||||
static int ipv4_tx ( struct pk_buff *pkb,
|
static int ipv4_tx ( struct pk_buff *pkb,
|
||||||
struct tcpip_protocol *tcpip_protocol,
|
struct tcpip_protocol *tcpip_protocol,
|
||||||
struct sockaddr_tcpip *st_dest, uint16_t *trans_csum ) {
|
struct sockaddr_tcpip *st_dest,
|
||||||
|
struct net_device *netdev,
|
||||||
|
uint16_t *trans_csum ) {
|
||||||
struct iphdr *iphdr = pkb_push ( pkb, sizeof ( *iphdr ) );
|
struct iphdr *iphdr = pkb_push ( pkb, sizeof ( *iphdr ) );
|
||||||
struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
|
struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
|
||||||
struct ipv4_miniroute *miniroute;
|
struct ipv4_miniroute *miniroute;
|
||||||
|
@ -388,28 +391,29 @@ static int ipv4_tx ( struct pk_buff *pkb,
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Fill up the IP header, except source address */
|
/* Fill up the IP header, except source address */
|
||||||
|
memset ( iphdr, 0, sizeof ( *iphdr ) );
|
||||||
iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
|
iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
|
||||||
iphdr->service = IP_TOS;
|
iphdr->service = IP_TOS;
|
||||||
iphdr->len = htons ( pkb_len ( pkb ) );
|
iphdr->len = htons ( pkb_len ( pkb ) );
|
||||||
iphdr->ident = htons ( ++next_ident );
|
iphdr->ident = htons ( ++next_ident );
|
||||||
iphdr->frags = 0;
|
|
||||||
iphdr->ttl = IP_TTL;
|
iphdr->ttl = IP_TTL;
|
||||||
iphdr->protocol = tcpip_protocol->tcpip_proto;
|
iphdr->protocol = tcpip_protocol->tcpip_proto;
|
||||||
iphdr->chksum = 0;
|
|
||||||
iphdr->dest = sin_dest->sin_addr;
|
iphdr->dest = sin_dest->sin_addr;
|
||||||
|
|
||||||
/* Use routing table to identify next hop and transmitting netdev */
|
/* Use routing table to identify next hop and transmitting netdev */
|
||||||
next_hop = iphdr->dest;
|
next_hop = iphdr->dest;
|
||||||
miniroute = ipv4_route ( &next_hop );
|
if ( ( miniroute = ipv4_route ( &next_hop ) ) ) {
|
||||||
if ( ! miniroute ) {
|
iphdr->src = miniroute->address;
|
||||||
|
netdev = miniroute->netdev;
|
||||||
|
}
|
||||||
|
if ( ! netdev ) {
|
||||||
DBG ( "IPv4 has no route to %s\n", inet_ntoa ( iphdr->dest ) );
|
DBG ( "IPv4 has no route to %s\n", inet_ntoa ( iphdr->dest ) );
|
||||||
rc = -EHOSTUNREACH;
|
rc = -EHOSTUNREACH;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
iphdr->src = miniroute->address;
|
|
||||||
|
|
||||||
/* Determine link-layer destination address */
|
/* Determine link-layer destination address */
|
||||||
if ( ( rc = ipv4_ll_addr ( next_hop, iphdr->src, miniroute->netdev,
|
if ( ( rc = ipv4_ll_addr ( next_hop, iphdr->src, netdev,
|
||||||
ll_dest ) ) != 0 ) {
|
ll_dest ) ) != 0 ) {
|
||||||
DBG ( "IPv4 has no link-layer address for %s\n",
|
DBG ( "IPv4 has no link-layer address for %s\n",
|
||||||
inet_ntoa ( iphdr->dest ) );
|
inet_ntoa ( iphdr->dest ) );
|
||||||
|
@ -428,7 +432,7 @@ static int ipv4_tx ( struct pk_buff *pkb,
|
||||||
ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
|
ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
|
||||||
|
|
||||||
/* Hand off to link layer */
|
/* Hand off to link layer */
|
||||||
return net_tx ( pkb, miniroute->netdev, &ipv4_protocol, ll_dest );
|
return net_tx ( pkb, netdev, &ipv4_protocol, ll_dest );
|
||||||
|
|
||||||
err:
|
err:
|
||||||
free_pkb ( pkb );
|
free_pkb ( pkb );
|
||||||
|
|
|
@ -202,11 +202,11 @@ void ipv6_dump ( struct ip6_header *ip6hdr ) {
|
||||||
static int ipv6_tx ( struct pk_buff *pkb,
|
static int ipv6_tx ( struct pk_buff *pkb,
|
||||||
struct tcpip_protocol *tcpip,
|
struct tcpip_protocol *tcpip,
|
||||||
struct sockaddr_tcpip *st_dest,
|
struct sockaddr_tcpip *st_dest,
|
||||||
|
struct net_device *netdev,
|
||||||
uint16_t *trans_csum ) {
|
uint16_t *trans_csum ) {
|
||||||
struct sockaddr_in6 *dest = ( struct sockaddr_in6* ) st_dest;
|
struct sockaddr_in6 *dest = ( struct sockaddr_in6* ) st_dest;
|
||||||
struct in6_addr next_hop;
|
struct in6_addr next_hop;
|
||||||
struct ipv6_miniroute *miniroute;
|
struct ipv6_miniroute *miniroute;
|
||||||
struct net_device *netdev = NULL;
|
|
||||||
uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
|
uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
|
||||||
const uint8_t *ll_dest = ll_dest_buf;
|
const uint8_t *ll_dest = ll_dest_buf;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
|
@ -309,7 +309,8 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
|
||||||
DBGC ( conn, "\n" );
|
DBGC ( conn, "\n" );
|
||||||
|
|
||||||
/* Transmit packet */
|
/* Transmit packet */
|
||||||
return tcpip_tx ( pkb, &tcp_protocol, &conn->peer, &tcphdr->csum );
|
return tcpip_tx ( pkb, &tcp_protocol, &conn->peer,
|
||||||
|
NULL, &tcphdr->csum );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -465,7 +466,8 @@ static int tcp_send_reset ( struct tcp_connection *conn,
|
||||||
DBGC ( conn, "\n" );
|
DBGC ( conn, "\n" );
|
||||||
|
|
||||||
/* Transmit packet */
|
/* Transmit packet */
|
||||||
return tcpip_tx ( pkb, &tcp_protocol, &conn->peer, &tcphdr->csum );
|
return tcpip_tx ( pkb, &tcp_protocol, &conn->peer,
|
||||||
|
NULL, &tcphdr->csum );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -65,11 +65,13 @@ int tcpip_rx ( struct pk_buff *pkb, uint8_t tcpip_proto,
|
||||||
* @v pkb Packet buffer
|
* @v pkb Packet buffer
|
||||||
* @v tcpip_protocol Transport-layer protocol
|
* @v tcpip_protocol Transport-layer protocol
|
||||||
* @v st_dest Destination address
|
* @v st_dest Destination address
|
||||||
|
* @v netdev Network device (or NULL to route automatically)
|
||||||
* @v trans_csum Transport-layer checksum to complete, or NULL
|
* @v trans_csum Transport-layer checksum to complete, or NULL
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int tcpip_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip_protocol,
|
int tcpip_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip_protocol,
|
||||||
struct sockaddr_tcpip *st_dest, uint16_t *trans_csum ) {
|
struct sockaddr_tcpip *st_dest, struct net_device *netdev,
|
||||||
|
uint16_t *trans_csum ) {
|
||||||
struct tcpip_net_protocol *tcpip_net;
|
struct tcpip_net_protocol *tcpip_net;
|
||||||
|
|
||||||
/* Hand off packet to the appropriate network-layer protocol */
|
/* Hand off packet to the appropriate network-layer protocol */
|
||||||
|
@ -78,7 +80,7 @@ int tcpip_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip_protocol,
|
||||||
if ( tcpip_net->sa_family == st_dest->st_family ) {
|
if ( tcpip_net->sa_family == st_dest->st_family ) {
|
||||||
DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
|
DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
|
||||||
return tcpip_net->tx ( pkb, tcpip_protocol, st_dest,
|
return tcpip_net->tx ( pkb, tcpip_protocol, st_dest,
|
||||||
trans_csum );
|
netdev, trans_csum );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,7 @@ int udp_sendto ( struct udp_connection *conn, struct sockaddr_tcpip *peer,
|
||||||
ntohs ( udphdr->len ) );
|
ntohs ( udphdr->len ) );
|
||||||
|
|
||||||
/* Send it to the next layer for processing */
|
/* Send it to the next layer for processing */
|
||||||
return tcpip_tx ( pkb, &udp_protocol, peer, &udphdr->chksum );
|
return tcpip_tx ( pkb, &udp_protocol, peer, NULL, &udphdr->chksum );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue