diff --git a/src/include/gpxe/ip.h b/src/include/gpxe/ip.h index 4f0f42f8..17aa3ceb 100644 --- a/src/include/gpxe/ip.h +++ b/src/include/gpxe/ip.h @@ -66,6 +66,6 @@ extern void del_ipv4_address ( struct net_device *netdev ); extern int ipv4_uip_tx ( struct pk_buff *pkb ); extern int ipv4_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip, - struct in_addr *dest ); + struct sockaddr *sock ); #endif /* _GPXE_IP_H */ diff --git a/src/include/gpxe/tcpip.h b/src/include/gpxe/tcpip.h index aa2ccd5d..4134de75 100644 --- a/src/include/gpxe/tcpip.h +++ b/src/include/gpxe/tcpip.h @@ -31,7 +31,9 @@ struct tcpip_protocol { * * This method takes ownership of the packet buffer. */ - void ( * rx ) ( struct pk_buff *pkb, struct in_addr *src_net_addr, struct in_addr *dest_net_addr ); + void ( * rx ) ( struct pk_buff *pkb, struct in_addr *src_net_addr, + struct in_addr *dest_net_addr ); + /** * Transport-layer protocol number * @@ -42,8 +44,8 @@ struct tcpip_protocol { * Checksum offset * * A negative number indicates that the protocol does not require - * checksumming to be performed by the network layer. A positive number is - * the offset of the checksum field in the transport-layer header. + * checksumming to be performed by the network layer. A positive number + * is the offset of the checksum field in the transport-layer header. */ int csum_offset; }; @@ -56,6 +58,15 @@ struct tcpip_net_protocol { struct net_protocol *net_protocol; /** Network address family */ sa_family_t sa_family; + /** + * Transmit packet + * + * @v pkb Packet buffer + * @v tcpip Transport-layer TCP/IP protocol + * @v sock Socket address + */ + int ( * tx ) ( struct pk_buff *pkb, struct tcpip_protocol *tcpip, + struct sockaddr *sock ); /** Complete transport-layer checksum calculation * * @v pkb Packet buffer diff --git a/src/net/ipv4.c b/src/net/ipv4.c index 4190ef73..147d2672 100644 --- a/src/net/ipv4.c +++ b/src/net/ipv4.c @@ -347,7 +347,8 @@ int ipv4_uip_tx ( struct pk_buff *pkb ) { * This function expects a transport-layer segment and prepends the IP header */ int ipv4_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip, - struct in_addr *dest ) { + struct sockaddr* sock ) { + struct in_addr *dest = &sock->sin.sin_addr; struct iphdr *iphdr = pkb_push ( pkb, sizeof ( *iphdr ) ); struct ipv4_miniroute *miniroute; struct net_device *netdev = NULL; @@ -613,6 +614,8 @@ NET_PROTOCOL ( ipv4_protocol ); /** IPv4 TCPIP net protocol */ struct tcpip_net_protocol ipv4_tcpip_protocol = { .net_protocol = &ipv4_protocol, + .sa_family = AF_INET, + .tx = ipv4_tx, .tx_csum = ipv4_tx_csum, }; diff --git a/src/net/ipv6.c b/src/net/ipv6.c index e726bda7..9825a61a 100644 --- a/src/net/ipv6.c +++ b/src/net/ipv6.c @@ -1,12 +1,16 @@ #include +#include +#include +#include +#include #include #include #include +#include +#include /** * Transmit IP6 packets - * - * Placeholder to allow linking. The function should be placed in net/ipv6.c */ int ipv6_tx ( struct pk_buff *pkb __unused, uint16_t trans_proto __unused, struct in6_addr *dest __unused) { @@ -22,3 +26,33 @@ void ipv6_rx ( struct pk_buff *pkb __unused, struct net_device *netdev __unused, const void *ll_source __unused ) { } + +void ipv6_tx_csum ( struct pk_buff *pkb, struct tcpip_protocol *tcpip ) { + return; +} + +static const char * ipv6_ntoa ( const void *net_addr ) { +// return inet6_ntoa ( * ( ( struct in6_addr * ) net_addr ) ); + return "no support yet"; +} + +/** IPv6 protocol */ +struct net_protocol ipv6_protocol = { + .name = "IP6", + .net_proto = htons ( ETH_P_IPV6 ), + .net_addr_len = sizeof ( struct in6_addr ), + .rx = ipv6_rx, + .ntoa = ipv6_ntoa, +}; + +NET_PROTOCOL ( ipv6_protocol ); + +/** IPv6 TCPIP net protocol */ +struct tcpip_net_protocol ipv6_tcpip_protocol = { + .net_protocol = &ipv6_protocol, + .sa_family = AF_INET6, + .tx = ipv6_tx, + .tx_csum = ipv6_tx_csum, +}; + +TCPIP_NET_PROTOCOL ( ipv6_tcpip_protocol ); diff --git a/src/net/tcpip.c b/src/net/tcpip.c index 22546a49..670d3375 100644 --- a/src/net/tcpip.c +++ b/src/net/tcpip.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,6 @@ void tcpip_rx ( struct pk_buff *pkb, uint8_t trans_proto, struct in_addr *src, /* Identify the transport layer protocol */ for ( tcpip = tcpip_protocols; tcpip <= tcpip_protocols_end; ++tcpip ) { if ( tcpip->trans_proto == trans_proto ) { - DBG ( "Packet sent to %s module", tcpip->name ); tcpip->rx ( pkb, src, dest ); } } @@ -57,17 +57,38 @@ void tcpip_rx ( struct pk_buff *pkb, uint8_t trans_proto, struct in_addr *src, int tcpip_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip, struct sockaddr *sock ) { +#if 0 /* This is the right thing to do */ + + struct tcpip_net_protocol *tcpip_net; + + /* Identify the network layer protocol */ + for ( tcpip_net = tcpip_net_protocols; + tcpip_net <= tcpip_net_protocols_end; ++tcpip_net ) { + if ( tcpip_net->sa_family == sock->sa_family ) { + DBG ( "Packet sent to %s module\n", tcpip_net->net_protocol->name ); + return tcpip_net->tx ( pkb, tcpip, sock ); + } + } + DBG ( "No suitable network layer protocol found for sa_family %s\n", + ( sock->sa_family ); + return -EAFNOSUPPORT; +} + +#else + /* Identify the network layer protocol and send it using xxx_tx() */ switch ( sock->sa_family ) { case AF_INET: /* IPv4 network family */ - return ipv4_tx ( pkb, tcpip, &sock->sin.sin_addr ); + return ipv4_tx ( pkb, tcpip, sock ); case AF_INET6: /* IPv6 network family */ - return ipv6_tx ( pkb, tcpip, &sock->sin6.sin6_addr ); + return ipv6_tx ( pkb, tcpip, sock ); } DBG ( "Network family %d not supported", sock->sa_family ); return -EAFNOSUPPORT; } +#endif + /** * Calculate continued TCP/IP checkum *