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 */
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 );
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
*
.name = "IPv4",
.sa_family = AF_INET,
.tx = ipv4_tx,
+ .netdev = ipv4_netdev,
};
/** IPv4 ARP protocol */
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
*
.name = "IPv6",
.sa_family = AF_INET6,
.tx = ipv6_tx,
+ .netdev = ipv6_netdev,
};
/** IPv6 socket address converter */
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
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
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
*