|
@@ -372,6 +372,7 @@ static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
|
372
|
372
|
* @v pkb Packet buffer
|
373
|
373
|
* @v tcpip Transport-layer protocol
|
374
|
374
|
* @v st_dest Destination network-layer address
|
|
375
|
+ * @v netdev Network device (or NULL to route automatically)
|
375
|
376
|
* @v trans_csum Transport-layer checksum to complete, or NULL
|
376
|
377
|
* @ret rc Status
|
377
|
378
|
*
|
|
@@ -379,7 +380,9 @@ static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
|
379
|
380
|
*/
|
380
|
381
|
static int ipv4_tx ( struct pk_buff *pkb,
|
381
|
382
|
struct tcpip_protocol *tcpip_protocol,
|
382
|
|
- struct sockaddr_tcpip *st_dest, uint16_t *trans_csum ) {
|
|
383
|
+ struct sockaddr_tcpip *st_dest,
|
|
384
|
+ struct net_device *netdev,
|
|
385
|
+ uint16_t *trans_csum ) {
|
383
|
386
|
struct iphdr *iphdr = pkb_push ( pkb, sizeof ( *iphdr ) );
|
384
|
387
|
struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
|
385
|
388
|
struct ipv4_miniroute *miniroute;
|
|
@@ -388,28 +391,29 @@ static int ipv4_tx ( struct pk_buff *pkb,
|
388
|
391
|
int rc;
|
389
|
392
|
|
390
|
393
|
/* Fill up the IP header, except source address */
|
|
394
|
+ memset ( iphdr, 0, sizeof ( *iphdr ) );
|
391
|
395
|
iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
|
392
|
396
|
iphdr->service = IP_TOS;
|
393
|
397
|
iphdr->len = htons ( pkb_len ( pkb ) );
|
394
|
398
|
iphdr->ident = htons ( ++next_ident );
|
395
|
|
- iphdr->frags = 0;
|
396
|
399
|
iphdr->ttl = IP_TTL;
|
397
|
400
|
iphdr->protocol = tcpip_protocol->tcpip_proto;
|
398
|
|
- iphdr->chksum = 0;
|
399
|
401
|
iphdr->dest = sin_dest->sin_addr;
|
400
|
402
|
|
401
|
403
|
/* Use routing table to identify next hop and transmitting netdev */
|
402
|
404
|
next_hop = iphdr->dest;
|
403
|
|
- miniroute = ipv4_route ( &next_hop );
|
404
|
|
- if ( ! miniroute ) {
|
|
405
|
+ if ( ( miniroute = ipv4_route ( &next_hop ) ) ) {
|
|
406
|
+ iphdr->src = miniroute->address;
|
|
407
|
+ netdev = miniroute->netdev;
|
|
408
|
+ }
|
|
409
|
+ if ( ! netdev ) {
|
405
|
410
|
DBG ( "IPv4 has no route to %s\n", inet_ntoa ( iphdr->dest ) );
|
406
|
411
|
rc = -EHOSTUNREACH;
|
407
|
412
|
goto err;
|
408
|
413
|
}
|
409
|
|
- iphdr->src = miniroute->address;
|
410
|
414
|
|
411
|
415
|
/* Determine link-layer destination address */
|
412
|
|
- if ( ( rc = ipv4_ll_addr ( next_hop, iphdr->src, miniroute->netdev,
|
|
416
|
+ if ( ( rc = ipv4_ll_addr ( next_hop, iphdr->src, netdev,
|
413
|
417
|
ll_dest ) ) != 0 ) {
|
414
|
418
|
DBG ( "IPv4 has no link-layer address for %s\n",
|
415
|
419
|
inet_ntoa ( iphdr->dest ) );
|
|
@@ -428,7 +432,7 @@ static int ipv4_tx ( struct pk_buff *pkb,
|
428
|
432
|
ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
|
429
|
433
|
|
430
|
434
|
/* Hand off to link layer */
|
431
|
|
- return net_tx ( pkb, miniroute->netdev, &ipv4_protocol, ll_dest );
|
|
435
|
+ return net_tx ( pkb, netdev, &ipv4_protocol, ll_dest );
|
432
|
436
|
|
433
|
437
|
err:
|
434
|
438
|
free_pkb ( pkb );
|