diff options
Diffstat (limited to 'gpxe/src/net/ipv6.c')
-rw-r--r-- | gpxe/src/net/ipv6.c | 381 |
1 files changed, 0 insertions, 381 deletions
diff --git a/gpxe/src/net/ipv6.c b/gpxe/src/net/ipv6.c deleted file mode 100644 index f7308bb4..00000000 --- a/gpxe/src/net/ipv6.c +++ /dev/null @@ -1,381 +0,0 @@ -#include <errno.h> -#include <stdint.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <byteswap.h> -#include <gpxe/in.h> -#include <gpxe/ip6.h> -#include <gpxe/ndp.h> -#include <gpxe/list.h> -#include <gpxe/icmp6.h> -#include <gpxe/tcpip.h> -#include <gpxe/socket.h> -#include <gpxe/iobuf.h> -#include <gpxe/netdevice.h> -#include <gpxe/if_ether.h> - -struct net_protocol ipv6_protocol; - -/* Unspecified IP6 address */ -static struct in6_addr ip6_none = { - .in6_u.u6_addr32 = { 0,0,0,0 } -}; - -/** An IPv6 routing table entry */ -struct ipv6_miniroute { - /* List of miniroutes */ - struct list_head list; - - /* Network device */ - struct net_device *netdev; - - /* Destination prefix */ - struct in6_addr prefix; - /* Prefix length */ - int prefix_len; - /* IPv6 address of interface */ - struct in6_addr address; - /* Gateway address */ - struct in6_addr gateway; -}; - -/** List of IPv6 miniroutes */ -static LIST_HEAD ( miniroutes ); - -/** - * Add IPv6 minirouting table entry - * - * @v netdev Network device - * @v prefix Destination prefix - * @v address Address of the interface - * @v gateway Gateway address (or ::0 for no gateway) - * @ret miniroute Routing table entry, or NULL - */ -static struct ipv6_miniroute * __malloc -add_ipv6_miniroute ( struct net_device *netdev, struct in6_addr prefix, - int prefix_len, struct in6_addr address, - struct in6_addr gateway ) { - struct ipv6_miniroute *miniroute; - - miniroute = malloc ( sizeof ( *miniroute ) ); - if ( miniroute ) { - /* Record routing information */ - miniroute->netdev = netdev_get ( netdev ); - miniroute->prefix = prefix; - miniroute->prefix_len = prefix_len; - miniroute->address = address; - miniroute->gateway = gateway; - - /* Add miniroute to list of miniroutes */ - if ( !IP6_EQUAL ( gateway, ip6_none ) ) { - list_add_tail ( &miniroute->list, &miniroutes ); - } else { - list_add ( &miniroute->list, &miniroutes ); - } - } - - return miniroute; -} - -/** - * Delete IPv6 minirouting table entry - * - * @v miniroute Routing table entry - */ -static void del_ipv6_miniroute ( struct ipv6_miniroute *miniroute ) { - netdev_put ( miniroute->netdev ); - list_del ( &miniroute->list ); - free ( miniroute ); -} - -/** - * Add IPv6 interface - * - * @v netdev Network device - * @v prefix Destination prefix - * @v address Address of the interface - * @v gateway Gateway address (or ::0 for no gateway) - */ -int add_ipv6_address ( struct net_device *netdev, struct in6_addr prefix, - int prefix_len, struct in6_addr address, - struct in6_addr gateway ) { - struct ipv6_miniroute *miniroute; - - /* Clear any existing address for this net device */ - del_ipv6_address ( netdev ); - - /* Add new miniroute */ - miniroute = add_ipv6_miniroute ( netdev, prefix, prefix_len, address, - gateway ); - if ( ! miniroute ) - return -ENOMEM; - - return 0; -} - -/** - * Remove IPv6 interface - * - * @v netdev Network device - */ -void del_ipv6_address ( struct net_device *netdev ) { - struct ipv6_miniroute *miniroute; - - list_for_each_entry ( miniroute, &miniroutes, list ) { - if ( miniroute->netdev == netdev ) { - del_ipv6_miniroute ( miniroute ); - break; - } - } -} - -/** - * Calculate TCPIP checksum - * - * @v iobuf I/O buffer - * @v tcpip TCP/IP protocol - * - * This function constructs the pseudo header and completes the checksum in the - * upper layer header. - */ -static uint16_t ipv6_tx_csum ( struct io_buffer *iobuf, uint16_t csum ) { - struct ip6_header *ip6hdr = iobuf->data; - struct ipv6_pseudo_header pshdr; - - /* Calculate pseudo header */ - memset ( &pshdr, 0, sizeof ( pshdr ) ); - pshdr.src = ip6hdr->src; - pshdr.dest = ip6hdr->dest; - pshdr.len = htons ( iob_len ( iobuf ) - sizeof ( *ip6hdr ) ); - pshdr.nxt_hdr = ip6hdr->nxt_hdr; - - /* Update checksum value */ - return tcpip_continue_chksum ( csum, &pshdr, sizeof ( pshdr ) ); -} - -/** - * Dump IP6 header for debugging - * - * ip6hdr IPv6 header - */ -void ipv6_dump ( struct ip6_header *ip6hdr ) { - DBG ( "IP6 %p src %s dest %s nxt_hdr %d len %d\n", ip6hdr, - inet6_ntoa ( ip6hdr->src ), inet6_ntoa ( ip6hdr->dest ), - ip6hdr->nxt_hdr, ntohs ( ip6hdr->payload_len ) ); -} - -/** - * Transmit IP6 packet - * - * iobuf I/O buffer - * tcpip TCP/IP protocol - * st_dest Destination socket address - * - * This function prepends the IPv6 headers to the payload an transmits it. - */ -static int ipv6_tx ( struct io_buffer *iobuf, - struct tcpip_protocol *tcpip, - struct sockaddr_tcpip *st_src __unused, - struct sockaddr_tcpip *st_dest, - struct net_device *netdev, - uint16_t *trans_csum ) { - struct sockaddr_in6 *dest = ( struct sockaddr_in6* ) st_dest; - struct in6_addr next_hop; - struct ipv6_miniroute *miniroute; - uint8_t ll_dest_buf[MAX_LL_ADDR_LEN]; - const uint8_t *ll_dest = ll_dest_buf; - int rc; - - /* Construct the IPv6 packet */ - struct ip6_header *ip6hdr = iob_push ( iobuf, sizeof ( *ip6hdr ) ); - memset ( ip6hdr, 0, sizeof ( *ip6hdr) ); - ip6hdr->ver_traffic_class_flow_label = htonl ( 0x60000000 );//IP6_VERSION; - ip6hdr->payload_len = htons ( iob_len ( iobuf ) - sizeof ( *ip6hdr ) ); - ip6hdr->nxt_hdr = tcpip->tcpip_proto; - ip6hdr->hop_limit = IP6_HOP_LIMIT; // 255 - - /* Determine the next hop address and interface - * - * TODO: Implement the routing table. - */ - next_hop = dest->sin6_addr; - list_for_each_entry ( miniroute, &miniroutes, list ) { - if ( ( memcmp ( &ip6hdr->dest, &miniroute->prefix, - miniroute->prefix_len ) == 0 ) || - ( IP6_EQUAL ( miniroute->gateway, ip6_none ) ) ) { - netdev = miniroute->netdev; - ip6hdr->src = miniroute->address; - if ( ! ( IS_UNSPECIFIED ( miniroute->gateway ) ) ) { - next_hop = miniroute->gateway; - } - break; - } - } - /* No network interface identified */ - if ( !netdev ) { - DBG ( "No route to host %s\n", inet6_ntoa ( ip6hdr->dest ) ); - rc = -ENETUNREACH; - goto err; - } - - /* Complete the transport layer checksum */ - if ( trans_csum ) - *trans_csum = ipv6_tx_csum ( iobuf, *trans_csum ); - - /* Print IPv6 header */ - ipv6_dump ( ip6hdr ); - - /* Resolve link layer address */ - if ( next_hop.in6_u.u6_addr8[0] == 0xff ) { - ll_dest_buf[0] = 0x33; - ll_dest_buf[1] = 0x33; - ll_dest_buf[2] = next_hop.in6_u.u6_addr8[12]; - ll_dest_buf[3] = next_hop.in6_u.u6_addr8[13]; - ll_dest_buf[4] = next_hop.in6_u.u6_addr8[14]; - ll_dest_buf[5] = next_hop.in6_u.u6_addr8[15]; - } else { - /* Unicast address needs to be resolved by NDP */ - if ( ( rc = ndp_resolve ( netdev, &next_hop, &ip6hdr->src, - ll_dest_buf ) ) != 0 ) { - DBG ( "No entry for %s\n", inet6_ntoa ( next_hop ) ); - goto err; - } - } - - /* Transmit packet */ - return net_tx ( iobuf, netdev, &ipv6_protocol, ll_dest ); - - err: - free_iob ( iobuf ); - return rc; -} - -/** - * Process next IP6 header - * - * @v iobuf I/O buffer - * @v nxt_hdr Next header number - * @v src Source socket address - * @v dest Destination socket address - * - * Refer http://www.iana.org/assignments/ipv6-parameters for the numbers - */ -static int ipv6_process_nxt_hdr ( struct io_buffer *iobuf, uint8_t nxt_hdr, - struct sockaddr_tcpip *src, struct sockaddr_tcpip *dest ) { - switch ( nxt_hdr ) { - case IP6_HOPBYHOP: - case IP6_ROUTING: - case IP6_FRAGMENT: - case IP6_AUTHENTICATION: - case IP6_DEST_OPTS: - case IP6_ESP: - DBG ( "Function not implemented for header %d\n", nxt_hdr ); - return -ENOSYS; - case IP6_ICMP6: - break; - case IP6_NO_HEADER: - DBG ( "No next header\n" ); - return 0; - } - /* Next header is not a IPv6 extension header */ - return tcpip_rx ( iobuf, nxt_hdr, src, dest, 0 /* fixme */ ); -} - -/** - * Process incoming IP6 packets - * - * @v iobuf I/O buffer - * @v netdev Network device - * @v ll_source Link-layer source address - * - * This function processes a IPv6 packet - */ -static int ipv6_rx ( struct io_buffer *iobuf, - __unused struct net_device *netdev, - __unused const void *ll_source ) { - - struct ip6_header *ip6hdr = iobuf->data; - union { - struct sockaddr_in6 sin6; - struct sockaddr_tcpip st; - } src, dest; - - /* Sanity check */ - if ( iob_len ( iobuf ) < sizeof ( *ip6hdr ) ) { - DBG ( "Packet too short (%zd bytes)\n", iob_len ( iobuf ) ); - goto drop; - } - - /* TODO: Verify checksum */ - - /* Print IP6 header for debugging */ - ipv6_dump ( ip6hdr ); - - /* Check header version */ - if ( ( ip6hdr->ver_traffic_class_flow_label & 0xf0000000 ) != 0x60000000 ) { - DBG ( "Invalid protocol version\n" ); - goto drop; - } - - /* Check the payload length */ - if ( ntohs ( ip6hdr->payload_len ) > iob_len ( iobuf ) ) { - DBG ( "Inconsistent packet length (%d bytes)\n", - ip6hdr->payload_len ); - goto drop; - } - - /* Ignore the traffic class and flow control values */ - - /* Construct socket address */ - memset ( &src, 0, sizeof ( src ) ); - src.sin6.sin_family = AF_INET6; - src.sin6.sin6_addr = ip6hdr->src; - memset ( &dest, 0, sizeof ( dest ) ); - dest.sin6.sin_family = AF_INET6; - dest.sin6.sin6_addr = ip6hdr->dest; - - /* Strip header */ - iob_unput ( iobuf, iob_len ( iobuf ) - ntohs ( ip6hdr->payload_len ) - - sizeof ( *ip6hdr ) ); - iob_pull ( iobuf, sizeof ( *ip6hdr ) ); - - /* Send it to the transport layer */ - return ipv6_process_nxt_hdr ( iobuf, ip6hdr->nxt_hdr, &src.st, &dest.st ); - - drop: - DBG ( "Packet dropped\n" ); - free_iob ( iobuf ); - return -1; -} - -/** - * Print a IP6 address as xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx - */ -char * inet6_ntoa ( struct in6_addr in6 ) { - static char buf[40]; - uint16_t *bytes = ( uint16_t* ) &in6; - sprintf ( buf, "%x:%x:%x:%x:%x:%x:%x:%x", bytes[0], bytes[1], bytes[2], - bytes[3], bytes[4], bytes[5], bytes[6], bytes[7] ); - return buf; -} - -static const char * ipv6_ntoa ( const void *net_addr ) { - return inet6_ntoa ( * ( ( struct in6_addr * ) net_addr ) ); -} - -/** IPv6 protocol */ -struct net_protocol ipv6_protocol __net_protocol = { - .name = "IPv6", - .net_proto = htons ( ETH_P_IPV6 ), - .net_addr_len = sizeof ( struct in6_addr ), - .rx = ipv6_rx, - .ntoa = ipv6_ntoa, -}; - -/** IPv6 TCPIP net protocol */ -struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol = { - .name = "IPv6", - .sa_family = AF_INET6, - .tx = ipv6_tx, -}; |