ipv6.c File Reference

#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>

Go to the source code of this file.

Data Structures

struct  ipv6_miniroute
 An IPv6 routing table entry. More...

Functions

static LIST_HEAD (miniroutes)
 List of IPv6 miniroutes.
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)
 Add IPv6 minirouting table entry.
static void del_ipv6_miniroute (struct ipv6_miniroute *miniroute)
 Delete IPv6 minirouting table entry.
int add_ipv6_address (struct net_device *netdev, struct in6_addr prefix, int prefix_len, struct in6_addr address, struct in6_addr gateway)
 Add IPv6 interface.
void del_ipv6_address (struct net_device *netdev)
 Remove IPv6 interface.
static uint16_t ipv6_tx_csum (struct io_buffer *iobuf, uint16_t csum)
 Calculate TCPIP checksum.
void ipv6_dump (struct ip6_header *ip6hdr)
 Dump IP6 header for debugging.
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)
 Transmit IP6 packet.
static int ipv6_process_nxt_hdr (struct io_buffer *iobuf, uint8_t nxt_hdr, struct sockaddr_tcpip *src, struct sockaddr_tcpip *dest)
 Process next IP6 header.
static int ipv6_rx (struct io_buffer *iobuf, __unused struct net_device *netdev, __unused const void *ll_source)
 Process incoming IP6 packets.
char * inet6_ntoa (struct in6_addr in6)
 Print a IP6 address as xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx.
static const char * ipv6_ntoa (const void *net_addr)

Variables

struct net_protocol ipv6_protocol
static struct in6_addr ip6_none
struct net_protocol ipv6_protocol __net_protocol
 IPv6 protocol.
struct tcpip_net_protocol
ipv6_tcpip_protocol 
__tcpip_net_protocol
 IPv6 TCPIP net protocol.


Function Documentation

static LIST_HEAD ( miniroutes   )  [static]

List of IPv6 miniroutes.

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 
) [static, read]

Add IPv6 minirouting table entry.

Parameters:
netdev Network device
prefix Destination prefix
address Address of the interface
gateway Gateway address (or ::0 for no gateway)
Return values:
miniroute Routing table entry, or NULL

Definition at line 56 of file ipv6.c.

References ipv6_miniroute::address, ipv6_miniroute::gateway, IP6_EQUAL, ipv6_miniroute::list, list_add, list_add_tail, malloc(), ipv6_miniroute::netdev, netdev_get(), ipv6_miniroute::prefix, and ipv6_miniroute::prefix_len.

Referenced by add_ipv6_address().

00058                                                {
00059         struct ipv6_miniroute *miniroute;
00060         
00061         miniroute = malloc ( sizeof ( *miniroute ) );
00062         if ( miniroute ) {
00063                 /* Record routing information */
00064                 miniroute->netdev = netdev_get ( netdev );
00065                 miniroute->prefix = prefix;
00066                 miniroute->prefix_len = prefix_len;
00067                 miniroute->address = address;
00068                 miniroute->gateway = gateway;
00069                 
00070                 /* Add miniroute to list of miniroutes */
00071                 if ( !IP6_EQUAL ( gateway, ip6_none ) ) {
00072                         list_add_tail ( &miniroute->list, &miniroutes );
00073                 } else {
00074                         list_add ( &miniroute->list, &miniroutes );
00075                 }
00076         }
00077 
00078         return miniroute;
00079 }

static void del_ipv6_miniroute ( struct ipv6_miniroute miniroute  )  [static]

Delete IPv6 minirouting table entry.

Parameters:
miniroute Routing table entry

Definition at line 86 of file ipv6.c.

References free(), ipv6_miniroute::list, list_del, ipv6_miniroute::netdev, and netdev_put().

Referenced by del_ipv6_address().

00086                                                                     {
00087         netdev_put ( miniroute->netdev );
00088         list_del ( &miniroute->list );
00089         free ( miniroute );
00090 }

int add_ipv6_address ( struct net_device netdev,
struct in6_addr  prefix,
int  prefix_len,
struct in6_addr  address,
struct in6_addr  gateway 
)

Add IPv6 interface.

Parameters:
netdev Network device
prefix Destination prefix
address Address of the interface
gateway Gateway address (or ::0 for no gateway)

Definition at line 100 of file ipv6.c.

References add_ipv6_miniroute(), del_ipv6_address(), and ENOMEM.

00102                                                  {
00103         struct ipv6_miniroute *miniroute;
00104 
00105         /* Clear any existing address for this net device */
00106         del_ipv6_address ( netdev );
00107 
00108         /* Add new miniroute */
00109         miniroute = add_ipv6_miniroute ( netdev, prefix, prefix_len, address,
00110                                          gateway );
00111         if ( ! miniroute )
00112                 return -ENOMEM;
00113 
00114         return 0;
00115 }

void del_ipv6_address ( struct net_device netdev  ) 

Remove IPv6 interface.

Parameters:
netdev Network device

Definition at line 122 of file ipv6.c.

References del_ipv6_miniroute(), ipv6_miniroute::list, list_for_each_entry, and ipv6_miniroute::netdev.

Referenced by add_ipv6_address().

00122                                                     {
00123         struct ipv6_miniroute *miniroute;
00124 
00125         list_for_each_entry ( miniroute, &miniroutes, list ) {
00126                 if ( miniroute->netdev == netdev ) {
00127                         del_ipv6_miniroute ( miniroute );
00128                         break;
00129                 }
00130         }
00131 }

static uint16_t ipv6_tx_csum ( struct io_buffer iobuf,
uint16_t  csum 
) [static]

Calculate TCPIP checksum.

Parameters:
iobuf I/O buffer
tcpip TCP/IP protocol
This function constructs the pseudo header and completes the checksum in the upper layer header.

Definition at line 142 of file ipv6.c.

References io_buffer::data, ip6_header::dest, ipv6_pseudo_header::dest, htons, iob_len(), ipv6_pseudo_header::len, memset(), ip6_header::nxt_hdr, ipv6_pseudo_header::nxt_hdr, ip6_header::src, ipv6_pseudo_header::src, and tcpip_continue_chksum().

Referenced by ipv6_tx().

00142                                                                         {
00143         struct ip6_header *ip6hdr = iobuf->data;
00144         struct ipv6_pseudo_header pshdr;
00145 
00146         /* Calculate pseudo header */
00147         memset ( &pshdr, 0, sizeof ( pshdr ) );
00148         pshdr.src = ip6hdr->src;
00149         pshdr.dest = ip6hdr->dest;
00150         pshdr.len = htons ( iob_len ( iobuf ) - sizeof ( *ip6hdr ) );
00151         pshdr.nxt_hdr = ip6hdr->nxt_hdr;
00152 
00153         /* Update checksum value */
00154         return tcpip_continue_chksum ( csum, &pshdr, sizeof ( pshdr ) );
00155 }

void ipv6_dump ( struct ip6_header ip6hdr  ) 

Dump IP6 header for debugging.

ip6hdr IPv6 header

Definition at line 162 of file ipv6.c.

References DBG, ip6_header::dest, inet6_ntoa(), ntohs, ip6_header::nxt_hdr, ip6_header::payload_len, and ip6_header::src.

Referenced by ipv6_rx(), and ipv6_tx().

00162                                              {
00163         DBG ( "IP6 %p src %s dest %s nxt_hdr %d len %d\n", ip6hdr,
00164               inet6_ntoa ( ip6hdr->src ), inet6_ntoa ( ip6hdr->dest ),
00165               ip6hdr->nxt_hdr, ntohs ( ip6hdr->payload_len ) );
00166 }

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 
) [static]

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.

Definition at line 177 of file ipv6.c.

References ipv6_miniroute::address, DBG, ip6_header::dest, dest, ENETUNREACH, free_iob(), ipv6_miniroute::gateway, ip6_header::hop_limit, htonl, htons, in6_addr::in6_u, inet6_ntoa(), iob_len(), iob_push, IP6_EQUAL, IP6_HOP_LIMIT, ipv6_dump(), ipv6_protocol, ipv6_tx_csum(), IS_UNSPECIFIED, list_for_each_entry, MAX_LL_ADDR_LEN, memcmp(), memset(), ndp_resolve(), net_tx(), ipv6_miniroute::netdev, ip6_header::nxt_hdr, ip6_header::payload_len, ipv6_miniroute::prefix, ipv6_miniroute::prefix_len, sockaddr_in6::sin6_addr, ip6_header::src, tcpip_protocol::tcpip_proto, in6_addr::u6_addr8, and ip6_header::ver_traffic_class_flow_label.

00182                                             {
00183         struct sockaddr_in6 *dest = ( struct sockaddr_in6* ) st_dest;
00184         struct in6_addr next_hop;
00185         struct ipv6_miniroute *miniroute;
00186         uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
00187         const uint8_t *ll_dest = ll_dest_buf;
00188         int rc;
00189 
00190         /* Construct the IPv6 packet */
00191         struct ip6_header *ip6hdr = iob_push ( iobuf, sizeof ( *ip6hdr ) );
00192         memset ( ip6hdr, 0, sizeof ( *ip6hdr) );
00193         ip6hdr->ver_traffic_class_flow_label = htonl ( 0x60000000 );//IP6_VERSION;
00194         ip6hdr->payload_len = htons ( iob_len ( iobuf ) - sizeof ( *ip6hdr ) );
00195         ip6hdr->nxt_hdr = tcpip->tcpip_proto;
00196         ip6hdr->hop_limit = IP6_HOP_LIMIT; // 255
00197 
00198         /* Determine the next hop address and interface
00199          *
00200          * TODO: Implement the routing table.
00201          */
00202         next_hop = dest->sin6_addr;
00203         list_for_each_entry ( miniroute, &miniroutes, list ) {
00204                 if ( ( memcmp ( &ip6hdr->dest, &miniroute->prefix,
00205                                         miniroute->prefix_len ) == 0 ) ||
00206                      ( IP6_EQUAL ( miniroute->gateway, ip6_none ) ) ) {
00207                         netdev = miniroute->netdev;
00208                         ip6hdr->src = miniroute->address;
00209                         if ( ! ( IS_UNSPECIFIED ( miniroute->gateway ) ) ) {
00210                                 next_hop = miniroute->gateway;
00211                         }
00212                         break;
00213                 }
00214         }
00215         /* No network interface identified */
00216         if ( !netdev ) {
00217                 DBG ( "No route to host %s\n", inet6_ntoa ( ip6hdr->dest ) );
00218                 rc = -ENETUNREACH;
00219                 goto err;
00220         }
00221 
00222         /* Complete the transport layer checksum */
00223         if ( trans_csum )
00224                 *trans_csum = ipv6_tx_csum ( iobuf, *trans_csum );
00225 
00226         /* Print IPv6 header */
00227         ipv6_dump ( ip6hdr );
00228         
00229         /* Resolve link layer address */
00230         if ( next_hop.in6_u.u6_addr8[0] == 0xff ) {
00231                 ll_dest_buf[0] = 0x33;
00232                 ll_dest_buf[1] = 0x33;
00233                 ll_dest_buf[2] = next_hop.in6_u.u6_addr8[12];
00234                 ll_dest_buf[3] = next_hop.in6_u.u6_addr8[13];
00235                 ll_dest_buf[4] = next_hop.in6_u.u6_addr8[14];
00236                 ll_dest_buf[5] = next_hop.in6_u.u6_addr8[15];
00237         } else {
00238                 /* Unicast address needs to be resolved by NDP */
00239                 if ( ( rc = ndp_resolve ( netdev, &next_hop, &ip6hdr->src,
00240                                           ll_dest_buf ) ) != 0 ) {
00241                         DBG ( "No entry for %s\n", inet6_ntoa ( next_hop ) );
00242                         goto err;
00243                 }
00244         }
00245 
00246         /* Transmit packet */
00247         return net_tx ( iobuf, netdev, &ipv6_protocol, ll_dest );
00248 
00249   err:
00250         free_iob ( iobuf );
00251         return rc;
00252 }

static int ipv6_process_nxt_hdr ( struct io_buffer iobuf,
uint8_t  nxt_hdr,
struct sockaddr_tcpip src,
struct sockaddr_tcpip dest 
) [static]

Process next IP6 header.

Parameters:
iobuf I/O buffer
nxt_hdr Next header number
src Source socket address
dest Destination socket address
Refer http://www.iana.org/assignments/ipv6-parameters for the numbers

Definition at line 264 of file ipv6.c.

References DBG, ENOSYS, IP6_AUTHENTICATION, IP6_DEST_OPTS, IP6_ESP, IP6_FRAGMENT, IP6_HOPBYHOP, IP6_ICMP6, IP6_NO_HEADER, IP6_ROUTING, and tcpip_rx().

Referenced by ipv6_rx().

00265                                                                           {
00266         switch ( nxt_hdr ) {
00267         case IP6_HOPBYHOP: 
00268         case IP6_ROUTING: 
00269         case IP6_FRAGMENT: 
00270         case IP6_AUTHENTICATION: 
00271         case IP6_DEST_OPTS: 
00272         case IP6_ESP: 
00273                 DBG ( "Function not implemented for header %d\n", nxt_hdr );
00274                 return -ENOSYS;
00275         case IP6_ICMP6: 
00276                 break;
00277         case IP6_NO_HEADER: 
00278                 DBG ( "No next header\n" );
00279                 return 0;
00280         }
00281         /* Next header is not a IPv6 extension header */
00282         return tcpip_rx ( iobuf, nxt_hdr, src, dest, 0 /* fixme */ );
00283 }

static int ipv6_rx ( struct io_buffer iobuf,
__unused struct net_device netdev,
__unused const void *  ll_source 
) [static]

Process incoming IP6 packets.

Parameters:
iobuf I/O buffer
netdev Network device
ll_source Link-layer source address
This function processes a IPv6 packet

Definition at line 294 of file ipv6.c.

References AF_INET6, io_buffer::data, DBG, ip6_header::dest, dest, free_iob(), iob_len(), iob_pull, iob_unput, ipv6_dump(), ipv6_process_nxt_hdr(), memset(), ntohs, ip6_header::nxt_hdr, ip6_header::payload_len, ip6_header::src, src, and ip6_header::ver_traffic_class_flow_label.

00296                                                       {
00297 
00298         struct ip6_header *ip6hdr = iobuf->data;
00299         union {
00300                 struct sockaddr_in6 sin6;
00301                 struct sockaddr_tcpip st;
00302         } src, dest;
00303 
00304         /* Sanity check */
00305         if ( iob_len ( iobuf ) < sizeof ( *ip6hdr ) ) {
00306                 DBG ( "Packet too short (%zd bytes)\n", iob_len ( iobuf ) );
00307                 goto drop;
00308         }
00309 
00310         /* TODO: Verify checksum */
00311 
00312         /* Print IP6 header for debugging */
00313         ipv6_dump ( ip6hdr );
00314 
00315         /* Check header version */
00316         if ( ( ip6hdr->ver_traffic_class_flow_label & 0xf0000000 ) != 0x60000000 ) {
00317                 DBG ( "Invalid protocol version\n" );
00318                 goto drop;
00319         }
00320 
00321         /* Check the payload length */
00322         if ( ntohs ( ip6hdr->payload_len ) > iob_len ( iobuf ) ) {
00323                 DBG ( "Inconsistent packet length (%d bytes)\n",
00324                         ip6hdr->payload_len );
00325                 goto drop;
00326         }
00327 
00328         /* Ignore the traffic class and flow control values */
00329 
00330         /* Construct socket address */
00331         memset ( &src, 0, sizeof ( src ) );
00332         src.sin6.sin_family = AF_INET6;
00333         src.sin6.sin6_addr = ip6hdr->src;
00334         memset ( &dest, 0, sizeof ( dest ) );
00335         dest.sin6.sin_family = AF_INET6;
00336         dest.sin6.sin6_addr = ip6hdr->dest;
00337 
00338         /* Strip header */
00339         iob_unput ( iobuf, iob_len ( iobuf ) - ntohs ( ip6hdr->payload_len ) -
00340                                                         sizeof ( *ip6hdr ) );
00341         iob_pull ( iobuf, sizeof ( *ip6hdr ) );
00342 
00343         /* Send it to the transport layer */
00344         return ipv6_process_nxt_hdr ( iobuf, ip6hdr->nxt_hdr, &src.st, &dest.st );
00345 
00346   drop:
00347         DBG ( "Packet dropped\n" );
00348         free_iob ( iobuf );
00349         return -1;
00350 }

char* inet6_ntoa ( struct in6_addr  in6  ) 

Print a IP6 address as xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx.

Definition at line 355 of file ipv6.c.

References sprintf.

Referenced by add_ndp_entry(), ipv6_dump(), ipv6_ntoa(), ipv6_tx(), and ndp_resolve().

00355                                           {
00356         static char buf[40];
00357         uint16_t *bytes = ( uint16_t* ) &in6;
00358         sprintf ( buf, "%x:%x:%x:%x:%x:%x:%x:%x", bytes[0], bytes[1], bytes[2],
00359                         bytes[3], bytes[4], bytes[5], bytes[6], bytes[7] );
00360         return buf;
00361 }

static const char* ipv6_ntoa ( const void *  net_addr  )  [static]

Definition at line 363 of file ipv6.c.

References inet6_ntoa().

00363                                                        {
00364         return inet6_ntoa ( * ( ( struct in6_addr * ) net_addr ) );
00365 }


Variable Documentation

Definition at line 18 of file ipv6.c.

Referenced by ipv6_tx().

struct in6_addr ip6_none [static]

Initial value:

 {
        .in6_u.u6_addr32 = { 0,0,0,0 }
}

Definition at line 21 of file ipv6.c.

Initial value:

 {
        .name = "IPv6",
        .net_proto = htons ( ETH_P_IPV6 ),
        .net_addr_len = sizeof ( struct in6_addr ),
        .rx = ipv6_rx,
        .ntoa = ipv6_ntoa,
}
IPv6 protocol.

AoE protocol.

Definition at line 368 of file ipv6.c.

Initial value:

 {
        .name = "IPv6",
        .sa_family = AF_INET6,
        .tx = ipv6_tx,
}
IPv6 TCPIP net protocol.

Definition at line 377 of file ipv6.c.


Generated on Tue Apr 6 20:01:55 2010 for gPXE by  doxygen 1.5.7.1