summaryrefslogtreecommitdiffstats
path: root/src/net/ipv4.c
diff options
context:
space:
mode:
authorMichael Brown2007-01-10 03:25:11 +0100
committerMichael Brown2007-01-10 03:25:11 +0100
commitf008b77ba2b7d921a9d765c9931694e9c7d13ee9 (patch)
tree1464a93bb9b01a2ae75ed87aa5b5d1e52b91392d /src/net/ipv4.c
parentAdd interface management commands (diff)
downloadipxe-f008b77ba2b7d921a9d765c9931694e9c7d13ee9.tar.gz
ipxe-f008b77ba2b7d921a9d765c9931694e9c7d13ee9.tar.xz
ipxe-f008b77ba2b7d921a9d765c9931694e9c7d13ee9.zip
Allow an explicit network device to be specified for IP-layer
transmissions.
Diffstat (limited to 'src/net/ipv4.c')
-rw-r--r--src/net/ipv4.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/src/net/ipv4.c b/src/net/ipv4.c
index e663ec32..a1a2d360 100644
--- a/src/net/ipv4.c
+++ b/src/net/ipv4.c
@@ -372,6 +372,7 @@ static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
* @v pkb Packet buffer
* @v tcpip Transport-layer protocol
* @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
* @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,
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 sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
struct ipv4_miniroute *miniroute;
@@ -388,28 +391,29 @@ static int ipv4_tx ( struct pk_buff *pkb,
int rc;
/* Fill up the IP header, except source address */
+ memset ( iphdr, 0, sizeof ( *iphdr ) );
iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
iphdr->service = IP_TOS;
iphdr->len = htons ( pkb_len ( pkb ) );
iphdr->ident = htons ( ++next_ident );
- iphdr->frags = 0;
iphdr->ttl = IP_TTL;
iphdr->protocol = tcpip_protocol->tcpip_proto;
- iphdr->chksum = 0;
iphdr->dest = sin_dest->sin_addr;
/* Use routing table to identify next hop and transmitting netdev */
next_hop = iphdr->dest;
- miniroute = ipv4_route ( &next_hop );
- if ( ! miniroute ) {
+ if ( ( miniroute = ipv4_route ( &next_hop ) ) ) {
+ iphdr->src = miniroute->address;
+ netdev = miniroute->netdev;
+ }
+ if ( ! netdev ) {
DBG ( "IPv4 has no route to %s\n", inet_ntoa ( iphdr->dest ) );
rc = -EHOSTUNREACH;
goto err;
}
- iphdr->src = miniroute->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 ) {
DBG ( "IPv4 has no link-layer address for %s\n",
inet_ntoa ( iphdr->dest ) );
@@ -428,7 +432,7 @@ static int ipv4_tx ( struct pk_buff *pkb,
ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
/* 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:
free_pkb ( pkb );