]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[tcpip] Provide tcpip_netdev() to determine the transmitting network device
authorMichael Brown <mcb30@ipxe.org>
Tue, 4 Mar 2014 12:54:21 +0000 (12:54 +0000)
committerMichael Brown <mcb30@ipxe.org>
Tue, 4 Mar 2014 13:02:58 +0000 (13:02 +0000)
Provide the function tcpip_netdev() to allow external code to
determine the transmitting network device for a given socket address.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/tcpip.h
src/net/ipv4.c
src/net/ipv6.c
src/net/tcpip.c

index f5ef4f0437333aad0dff2b7d45427df54f035b70..d28689a10a8b163a7aa158f8445f6ec31c025eba 100644 (file)
@@ -116,6 +116,13 @@ struct tcpip_net_protocol {
                       struct sockaddr_tcpip *st_dest,
                       struct net_device *netdev,
                       uint16_t *trans_csum );
+       /**
+        * Determine transmitting network device
+        *
+        * @v st_dest           Destination address
+        * @ret netdev          Network device, or NULL
+        */
+       struct net_device * ( * netdev ) ( struct sockaddr_tcpip *dest );
 };
 
 /** TCP/IP transport-layer protocol table */
@@ -140,6 +147,7 @@ extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
                      struct sockaddr_tcpip *st_dest,
                      struct net_device *netdev,
                      uint16_t *trans_csum );
+extern struct net_device * tcpip_netdev ( struct sockaddr_tcpip *st_dest );
 extern uint16_t generic_tcpip_continue_chksum ( uint16_t partial,
                                                const void *data, size_t len );
 extern uint16_t tcpip_chksum ( const void *data, size_t len );
index d9a54adebbc9c10a37d7e5392103560e6f92daaa..8bda5c86fd0b17c21e9c56b5e579aa20d8c67aba 100644 (file)
@@ -137,6 +137,25 @@ static struct ipv4_miniroute * ipv4_route ( struct in_addr *dest ) {
        return NULL;
 }
 
+/**
+ * Determine transmitting network device
+ *
+ * @v st_dest          Destination network-layer address
+ * @ret netdev         Transmitting network device, or NULL
+ */
+static struct net_device * ipv4_netdev ( struct sockaddr_tcpip *st_dest ) {
+       struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
+       struct in_addr dest = sin_dest->sin_addr;
+       struct ipv4_miniroute *miniroute;
+
+       /* Find routing table entry */
+       miniroute = ipv4_route ( &dest );
+       if ( ! miniroute )
+               return NULL;
+
+       return miniroute->netdev;
+}
+
 /**
  * Check if IPv4 fragment matches fragment reassembly buffer
  *
@@ -603,6 +622,7 @@ struct tcpip_net_protocol ipv4_tcpip_protocol __tcpip_net_protocol = {
        .name = "IPv4",
        .sa_family = AF_INET,
        .tx = ipv4_tx,
+       .netdev = ipv4_netdev,
 };
 
 /** IPv4 ARP protocol */
index 2802aef0545fff0799fc15add46a40ccecd80540..6f2e94776f69df894aff1da6ace2527b0c7b9dec 100644 (file)
@@ -321,6 +321,25 @@ static struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
        return NULL;
 }
 
+/**
+ * Determine transmitting network device
+ *
+ * @v st_dest          Destination network-layer address
+ * @ret netdev         Transmitting network device, or NULL
+ */
+static struct net_device * ipv6_netdev ( struct sockaddr_tcpip *st_dest ) {
+       struct sockaddr_in6 *sin6_dest = ( ( struct sockaddr_in6 * ) st_dest );
+       struct in6_addr *dest = &sin6_dest->sin6_addr;
+       struct ipv6_miniroute *miniroute;
+
+       /* Find routing table entry */
+       miniroute = ipv6_route ( sin6_dest->sin6_scope_id, &dest );
+       if ( ! miniroute )
+               return NULL;
+
+       return miniroute->netdev;
+}
+
 /**
  * Check that received options can be safely ignored
  *
@@ -970,6 +989,7 @@ struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol = {
        .name = "IPv6",
        .sa_family = AF_INET6,
        .tx = ipv6_tx,
+       .netdev = ipv6_netdev,
 };
 
 /** IPv6 socket address converter */
index 0b2adfd96dac0792b3730ba3aede08b9e9514fcc..6fac8c52cdda7dc9740ab9423f6863aa1d0f3300 100644 (file)
@@ -18,7 +18,8 @@
 
 FILE_LICENCE ( GPL2_OR_LATER );
 
-/** Process a received TCP/IP packet
+/**
+ * Process a received TCP/IP packet
  *
  * @v iobuf            I/O buffer
  * @v netdev           Network device
@@ -57,7 +58,27 @@ int tcpip_rx ( struct io_buffer *iobuf, struct net_device *netdev,
        return -EPROTONOSUPPORT;
 }
 
-/** Transmit a TCP/IP packet
+/**
+ * Find TCP/IP network-layer protocol
+ *
+ * @v st_dest          Destination address
+ * @ret tcpip_net      TCP/IP network-layer protocol, or NULL if not found
+ */
+static struct tcpip_net_protocol *
+tcpip_net_protocol ( struct sockaddr_tcpip *st_dest ) {
+       struct tcpip_net_protocol *tcpip_net;
+
+       for_each_table_entry ( tcpip_net, TCPIP_NET_PROTOCOLS ) {
+               if ( tcpip_net->sa_family == st_dest->st_family )
+                       return tcpip_net;
+       }
+
+       DBG ( "Unrecognised TCP/IP address family %d\n", st_dest->st_family );
+       return NULL;
+}
+
+/**
+ * Transmit a TCP/IP packet
  *
  * @v iobuf            I/O buffer
  * @v tcpip_protocol   Transport-layer protocol
@@ -73,19 +94,34 @@ int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
        struct tcpip_net_protocol *tcpip_net;
 
        /* Hand off packet to the appropriate network-layer protocol */
-       for_each_table_entry ( tcpip_net, TCPIP_NET_PROTOCOLS ) {
-               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_src,
-                                              st_dest, netdev, trans_csum );
-               }
+       tcpip_net = tcpip_net_protocol ( st_dest );
+       if ( tcpip_net ) {
+               DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
+               return tcpip_net->tx ( iobuf, tcpip_protocol, st_src, st_dest,
+                                      netdev, trans_csum );
        }
-       
-       DBG ( "Unrecognised TCP/IP address family %d\n", st_dest->st_family );
+
        free_iob ( iobuf );
        return -EAFNOSUPPORT;
 }
 
+/**
+ * Determine transmitting network device
+ *
+ * @v st_dest          Destination address
+ * @ret netdev         Network device, or NULL
+ */
+struct net_device * tcpip_netdev ( struct sockaddr_tcpip *st_dest ) {
+       struct tcpip_net_protocol *tcpip_net;
+
+       /* Hand off to the appropriate network-layer protocol */
+       tcpip_net = tcpip_net_protocol ( st_dest );
+       if ( tcpip_net )
+               return tcpip_net->netdev ( st_dest );
+
+       return NULL;
+}
+
 /**
  * Calculate continued TCP/IP checkum
  *