#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. | |
| 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.
| netdev | Network device | |
| prefix | Destination prefix | |
| address | Address of the interface | |
| gateway | Gateway address (or ::0 for no gateway) |
| 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.
| 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.
| 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.
| 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 }
Calculate TCPIP checksum.
| iobuf | I/O buffer | |
| tcpip | TCP/IP protocol |
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.
| iobuf | I/O buffer | |
| nxt_hdr | Next header number | |
| src | Source socket address | |
| dest | Destination socket address |
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.
| iobuf | I/O buffer | |
| netdev | Network device | |
| ll_source | Link-layer source address |
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 }
| struct net_protocol ipv6_protocol |
1.5.7.1