iPXE
ipv6.c File Reference

IPv6 protocol. More...

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <ipxe/iobuf.h>
#include <ipxe/tcpip.h>
#include <ipxe/if_ether.h>
#include <ipxe/crc32.h>
#include <ipxe/fragment.h>
#include <ipxe/ipstat.h>
#include <ipxe/ndp.h>
#include <ipxe/ipv6.h>

Go to the source code of this file.

Macros

#define EINVAL_LEN   __einfo_error ( EINFO_EINVAL_LEN )
#define EINFO_EINVAL_LEN    __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid length" )
#define ENOTSUP_VER   __einfo_error ( EINFO_ENOTSUP_VER )
#define EINFO_ENOTSUP_VER    __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported version" )
#define ENOTSUP_HDR   __einfo_error ( EINFO_ENOTSUP_HDR )
#define EINFO_ENOTSUP_HDR    __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported header type" )
#define ENOTSUP_OPT   __einfo_error ( EINFO_ENOTSUP_OPT )
#define EINFO_ENOTSUP_OPT    __einfo_uniqify ( EINFO_ENOTSUP, 0x03, "Unsupported option" )

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 FILE_SECBOOT (PERMITTED)
struct ip_statistics_family ipv6_statistics_family __ip_statistics_family (IP_STATISTICS_IPV6)
 IPv6 statistics family.
static uint32_t ipv6col (struct in6_addr *in)
 Determine debugging colour for IPv6 debug messages.
static unsigned int ipv6_scope (const struct in6_addr *addr)
 Determine IPv6 address scope.
static void ipv6_dump_miniroute (struct ipv6_miniroute *miniroute)
 Dump IPv6 routing table entry.
int ipv6_has_addr (struct net_device *netdev, struct in6_addr *addr)
 Check if network device has a specific IPv6 address.
static unsigned int ipv6_match_len (struct ipv6_miniroute *miniroute, struct in6_addr *address)
 Count matching bits of an IPv6 routing table entry prefix.
static struct ipv6_miniroute * ipv6_miniroute (struct net_device *netdev, struct in6_addr *address)
 Find IPv6 routing table entry for a given address.
int ipv6_add_miniroute (struct net_device *netdev, struct in6_addr *address, unsigned int prefix_len, struct in6_addr *router)
 Add IPv6 routing table entry.
void ipv6_del_miniroute (struct ipv6_miniroute *miniroute)
 Delete IPv6 minirouting table entry.
struct ipv6_minirouteipv6_route (unsigned int scope_id, struct in6_addr **dest)
 Perform IPv6 routing.
static struct net_deviceipv6_netdev (struct sockaddr_tcpip *st_dest)
 Determine transmitting network device.
static int ipv6_check_options (struct ipv6_header *iphdr, struct ipv6_options_header *options, size_t len)
 Check that received options can be safely ignored.
static int ipv6_is_fragment (struct fragment *fragment, struct io_buffer *iobuf, size_t hdrlen)
 Check if fragment matches fragment reassembly buffer.
static size_t ipv6_fragment_offset (struct io_buffer *iobuf, size_t hdrlen)
 Get fragment offset.
static int ipv6_more_fragments (struct io_buffer *iobuf, size_t hdrlen)
 Check if more fragments exist.
static uint16_t ipv6_pshdr_chksum (struct ipv6_header *iphdr, size_t len, int next_header, uint16_t csum)
 Calculate IPv6 pseudo-header checksum.
static int ipv6_tx (struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, struct net_device *netdev, uint16_t *trans_csum)
 Transmit IPv6 packet.
static int ipv6_rx (struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest __unused, const void *ll_source __unused, unsigned int flags __unused)
 Process incoming IPv6 packets.
int inet6_aton (const char *string, struct in6_addr *in)
 Parse IPv6 address.
char * inet6_ntoa (const struct in6_addr *in)
 Convert IPv6 address to standard notation.
static const char * ipv6_ntoa (const void *net_addr)
 Transcribe IPv6 address.
static const char * ipv6_sock_ntoa (struct sockaddr *sa)
 Transcribe IPv6 socket address.
static int ipv6_sock_aton (const char *string, struct sockaddr *sa)
 Parse IPv6 socket address.
int parse_ipv6_setting (const struct setting_type *type __unused, const char *value, void *buf, size_t len)
 Parse IPv6 address setting value.
int format_ipv6_setting (const struct setting_type *type __unused, const void *raw, size_t raw_len, char *buf, size_t len)
 Format IPv6 address setting value.
const struct setting ip6_setting __setting (SETTING_IP6, ip6)
 IPv6 address setting.
const struct setting len6_setting __setting (SETTING_IP6, len6)
 IPv6 prefix length setting.
const struct setting gateway6_setting __setting (SETTING_IP6, gateway6)
 Default gateway setting.
static int ipv6_applies (struct settings *settings __unused, const struct setting *setting)
 Check applicability of IPv6 link-local address setting.
static int ipv6_fetch (struct settings *settings, struct setting *setting, void *data, size_t len)
 Fetch IPv6 link-local address setting.
static int ipv6_register_settings (struct net_device *netdev, void *priv)
 Register IPv6 link-local address settings.
static int ipv6_create_routes (struct net_device *netdev, struct settings *settings)
 Create IPv6 routing table based on configured settings.
static int ipv6_create_all_routes (void)
 Create IPv6 routing table based on configured settings.
 REQUIRING_SYMBOL (ipv6_protocol)
 REQUIRE_OBJECT (icmpv6)
 REQUIRE_OBJECT (ndp)

Variables

struct list_head ipv6_miniroutes = LIST_HEAD_INIT ( ipv6_miniroutes )
 List of IPv6 miniroutes.
static struct ip_statistics ipv6_stats
 IPv6 statistics.
static struct fragment_reassembler ipv6_reassembler
 Fragment reassembler.
struct net_protocol ipv6_protocol __net_protocol
 IPv6 protocol.
struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol
 IPv6 TCPIP net protocol.
struct sockaddr_converter ipv6_sockaddr_converter __sockaddr_converter
 IPv6 socket address converter.
const struct settings_scope ipv6_settings_scope
 IPv6 settings scope.
static struct settings_operations ipv6_settings_operations
 IPv6 link-local address settings operations.
struct net_driver ipv6_driver __net_driver
 IPv6 network device driver.
struct settings_applicator ipv6_settings_applicator __settings_applicator
 IPv6 settings applicator.

Detailed Description

IPv6 protocol.

Definition in file ipv6.c.

Macro Definition Documentation

◆ EINVAL_LEN

#define EINVAL_LEN   __einfo_error ( EINFO_EINVAL_LEN )

Definition at line 47 of file ipv6.c.

Referenced by ipv6_rx().

◆ EINFO_EINVAL_LEN

#define EINFO_EINVAL_LEN    __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid length" )

Definition at line 48 of file ipv6.c.

48#define EINFO_EINVAL_LEN \
49 __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid length" )

◆ ENOTSUP_VER

#define ENOTSUP_VER   __einfo_error ( EINFO_ENOTSUP_VER )

Definition at line 50 of file ipv6.c.

Referenced by ipv6_rx().

◆ EINFO_ENOTSUP_VER

#define EINFO_ENOTSUP_VER    __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported version" )

Definition at line 51 of file ipv6.c.

51#define EINFO_ENOTSUP_VER \
52 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported version" )

◆ ENOTSUP_HDR

#define ENOTSUP_HDR   __einfo_error ( EINFO_ENOTSUP_HDR )

Definition at line 53 of file ipv6.c.

◆ EINFO_ENOTSUP_HDR

#define EINFO_ENOTSUP_HDR    __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported header type" )

Definition at line 54 of file ipv6.c.

54#define EINFO_ENOTSUP_HDR \
55 __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported header type" )

◆ ENOTSUP_OPT

#define ENOTSUP_OPT   __einfo_error ( EINFO_ENOTSUP_OPT )

Definition at line 56 of file ipv6.c.

Referenced by ipv6_check_options().

◆ EINFO_ENOTSUP_OPT

#define EINFO_ENOTSUP_OPT    __einfo_uniqify ( EINFO_ENOTSUP, 0x03, "Unsupported option" )

Definition at line 57 of file ipv6.c.

57#define EINFO_ENOTSUP_OPT \
58 __einfo_uniqify ( EINFO_ENOTSUP, 0x03, "Unsupported option" )

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ __ip_statistics_family()

struct ip_statistics_family ipv6_statistics_family __ip_statistics_family ( IP_STATISTICS_IPV6 )

IPv6 statistics family.

References __ip_statistics_family, IP_STATISTICS_IPV6, and ipv6_stats.

◆ ipv6col()

uint32_t ipv6col ( struct in6_addr * in)
static

Determine debugging colour for IPv6 debug messages.

Parameters
inIPv6 address
Return values
colDebugging colour (for DBGC())

Definition at line 79 of file ipv6.c.

79 {
80 return crc32_le ( 0, in, sizeof ( *in ) );
81}
__be32 in[4]
Definition CIB_PRM.h:7
u32 crc32_le(u32 seed, const void *data, size_t len)
Calculate 32-bit little-endian CRC checksum.
Definition crc32.c:40

References crc32_le(), and in.

Referenced by ipv6_check_options(), ipv6_rx(), and ipv6_tx().

◆ ipv6_scope()

unsigned int ipv6_scope ( const struct in6_addr * addr)
static

Determine IPv6 address scope.

Parameters
addrIPv6 address
Return values
scopeAddress scope

Definition at line 89 of file ipv6.c.

89 {
90
91 /* Multicast addresses directly include a scope field */
93 return ipv6_multicast_scope ( addr );
94
95 /* Link-local addresses have link-local scope */
98
99 /* Site-local addresses have site-local scope */
100 if ( IN6_IS_ADDR_SITELOCAL ( addr ) )
102
103 /* Unique local addresses do not directly map to a defined
104 * scope. They effectively have a scope which is wider than
105 * link-local but narrower than global. Since the only
106 * multicast packets that we transmit are link-local, we can
107 * simply choose an arbitrary scope between link-local and
108 * global.
109 */
110 if ( IN6_IS_ADDR_ULA ( addr ) )
112
113 /* All other addresses are assumed to be global */
114 return IPV6_SCOPE_GLOBAL;
115}
uint32_t addr
Buffer address.
Definition dwmac.h:9
#define IN6_IS_ADDR_SITELOCAL(addr)
Definition in.h:75
#define IN6_IS_ADDR_MULTICAST(addr)
Definition in.h:68
#define IN6_IS_ADDR_LINKLOCAL(addr)
Definition in.h:71
#define IN6_IS_ADDR_ULA(addr)
Definition in.h:79
static unsigned int ipv6_multicast_scope(const struct in6_addr *addr)
Get multicast address scope.
Definition ipv6.h:275
@ IPV6_SCOPE_SITE_LOCAL
Site-local address scope.
Definition ipv6.h:171
@ IPV6_SCOPE_GLOBAL
Global address scope.
Definition ipv6.h:175
@ IPV6_SCOPE_ORGANISATION_LOCAL
Organisation-local address scope.
Definition ipv6.h:173
@ IPV6_SCOPE_LINK_LOCAL
Link-local address scope.
Definition ipv6.h:167

References addr, IN6_IS_ADDR_LINKLOCAL, IN6_IS_ADDR_MULTICAST, IN6_IS_ADDR_SITELOCAL, IN6_IS_ADDR_ULA, ipv6_multicast_scope(), IPV6_SCOPE_GLOBAL, IPV6_SCOPE_LINK_LOCAL, IPV6_SCOPE_ORGANISATION_LOCAL, and IPV6_SCOPE_SITE_LOCAL.

Referenced by ipv6_add_miniroute(), and ipv6_route().

◆ ipv6_dump_miniroute()

void ipv6_dump_miniroute ( struct ipv6_miniroute * miniroute)
inlinestatic

Dump IPv6 routing table entry.

Parameters
minirouteRouting table entry

Definition at line 123 of file ipv6.c.

123 {
124 struct net_device *netdev = miniroute->netdev;
125
126 DBGC ( netdev, "IPv6 %s has %s %s/%d", netdev->name,
127 ( ( miniroute->flags & IPV6_HAS_ADDRESS ) ?
128 "address" : "prefix" ),
129 inet6_ntoa ( &miniroute->address ), miniroute->prefix_len );
130 if ( miniroute->flags & IPV6_HAS_ROUTER )
131 DBGC ( netdev, " router %s", inet6_ntoa ( &miniroute->router ));
132 DBGC ( netdev, "\n" );
133}
static struct net_device * netdev
Definition gdbudp.c:53
#define DBGC(...)
Definition compiler.h:505
char * inet6_ntoa(const struct in6_addr *in)
Convert IPv6 address to standard notation.
Definition ipv6.c:895
@ IPV6_HAS_ROUTER
Routing table entry router address is valid.
Definition ipv6.h:207
@ IPV6_HAS_ADDRESS
Routing table entry address is valid.
Definition ipv6.h:205
struct net_device * netdev
Network device.
Definition ipv6.h:186
unsigned int prefix_len
Prefix length.
Definition ipv6.h:191
unsigned int flags
Flags.
Definition ipv6.h:199
struct in6_addr router
Router address.
Definition ipv6.h:195
struct in6_addr address
IPv6 address (or prefix if no address is defined)
Definition ipv6.h:189
A network device.
Definition netdevice.h:353

References ipv6_miniroute::address, DBGC, ipv6_miniroute::flags, inet6_ntoa(), IPV6_HAS_ADDRESS, IPV6_HAS_ROUTER, ipv6_miniroute::netdev, netdev, ipv6_miniroute::prefix_len, and ipv6_miniroute::router.

Referenced by ipv6_add_miniroute().

◆ ipv6_has_addr()

int ipv6_has_addr ( struct net_device * netdev,
struct in6_addr * addr )

Check if network device has a specific IPv6 address.

Parameters
netdevNetwork device
addrIPv6 address
Return values
has_addrNetwork device has this IPv6 address

Definition at line 142 of file ipv6.c.

142 {
143 struct ipv6_miniroute *miniroute;
144
145 list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
146 if ( ( miniroute->netdev == netdev ) &&
147 ( miniroute->flags & IPV6_HAS_ADDRESS ) &&
148 ( memcmp ( &miniroute->address, addr,
149 sizeof ( miniroute->address ) ) == 0 ) ) {
150 /* Found matching address */
151 return 1;
152 }
153 }
154 return 0;
155}
struct list_head ipv6_miniroutes
List of IPv6 miniroutes.
Definition ipv6.c:61
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
An IPv6 address/routing table entry.
Definition ipv6.h:181
struct list_head list
List of miniroutes.
Definition ipv6.h:183

References addr, ipv6_miniroute::address, ipv6_miniroute::flags, IPV6_HAS_ADDRESS, ipv6_miniroutes, ipv6_miniroute::list, list_for_each_entry, memcmp(), ipv6_miniroute::netdev, and netdev.

Referenced by ipv6_rx(), and ndp_rx_neighbour_solicitation_ll_source().

◆ ipv6_match_len()

unsigned int ipv6_match_len ( struct ipv6_miniroute * miniroute,
struct in6_addr * address )
static

Count matching bits of an IPv6 routing table entry prefix.

Parameters
minirouteRouting table entry
addressIPv6 address
Return values
match_lenNumber of matching prefix bits

Definition at line 164 of file ipv6.c.

165 {
166 unsigned int match_len = 0;
167 unsigned int i;
168 uint32_t diff;
169
170 for ( i = 0 ; i < ( sizeof ( address->s6_addr32 ) /
171 sizeof ( address->s6_addr32[0] ) ) ; i++ ) {
172
173 diff = ntohl ( ~( ( ~( address->s6_addr32[i] ^
174 miniroute->address.s6_addr32[i] ) )
175 & miniroute->prefix_mask.s6_addr32[i] ) );
176 match_len += 32;
177 if ( diff ) {
178 match_len -= flsl ( diff );
179 break;
180 }
181 }
182
183 return match_len;
184}
unsigned int uint32_t
Definition stdint.h:12
uint64_t address
Base address.
Definition ena.h:13
#define ntohl(value)
Definition byteswap.h:135
#define flsl(x)
Find last (i.e.
Definition strings.h:158
struct in6_addr prefix_mask
IPv6 prefix mask (derived from prefix length)
Definition ipv6.h:193

References address, ipv6_miniroute::address, flsl, ntohl, and ipv6_miniroute::prefix_mask.

Referenced by ipv6_miniroute(), and ipv6_route().

◆ ipv6_miniroute()

struct ipv6_miniroute * ipv6_miniroute ( struct net_device * netdev,
struct in6_addr * address )
static

Find IPv6 routing table entry for a given address.

Parameters
netdevNetwork device
addressIPv6 address
Return values
minirouteRouting table entry, or NULL if not found

Definition at line 193 of file ipv6.c.

194 {
195 struct ipv6_miniroute *miniroute;
196 unsigned int match_len;
197
198 list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
199 if ( miniroute->netdev != netdev )
200 continue;
201 match_len = ipv6_match_len ( miniroute, address );
202 if ( match_len < miniroute->prefix_len )
203 continue;
204 return miniroute;
205 }
206 return NULL;
207}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
static unsigned int ipv6_match_len(struct ipv6_miniroute *miniroute, struct in6_addr *address)
Count matching bits of an IPv6 routing table entry prefix.
Definition ipv6.c:164

References address, ipv6_match_len(), ipv6_miniroutes, ipv6_miniroute::list, list_for_each_entry, ipv6_miniroute::netdev, netdev, NULL, and ipv6_miniroute::prefix_len.

Referenced by ipv6_add_miniroute().

◆ ipv6_add_miniroute()

int ipv6_add_miniroute ( struct net_device * netdev,
struct in6_addr * address,
unsigned int prefix_len,
struct in6_addr * router )

Add IPv6 routing table entry.

Parameters
netdevNetwork device
addressIPv6 address (or prefix)
prefix_lenPrefix length
routerRouter address (if any)
Return values
rcReturn status code

Definition at line 218 of file ipv6.c.

219 {
220 struct ipv6_miniroute *miniroute;
222 unsigned int remaining;
223 unsigned int i;
224
225 /* Find or create routing table entry */
226 miniroute = ipv6_miniroute ( netdev, address );
227 if ( miniroute ) {
228
229 /* Remove from existing position in routing table */
230 list_del ( &miniroute->list );
231
232 } else {
233
234 /* Create new routing table entry */
235 miniroute = zalloc ( sizeof ( *miniroute ) );
236 if ( ! miniroute )
237 return -ENOMEM;
238 miniroute->netdev = netdev_get ( netdev );
239 memcpy ( &miniroute->address, address,
240 sizeof ( miniroute->address ) );
241
242 /* Default to prefix length of 64 if none specified */
243 if ( ! prefix_len )
245 miniroute->prefix_len = prefix_len;
247
248 /* Construct prefix mask */
249 remaining = prefix_len;
250 for ( prefix_mask = miniroute->prefix_mask.s6_addr ;
251 remaining >= 8 ; prefix_mask++, remaining -= 8 ) {
252 *prefix_mask = 0xff;
253 }
254 if ( remaining )
255 *prefix_mask = ( 0xff << ( 8 - remaining ) );
256 }
257
258 /* Add to start of routing table */
259 list_add ( &miniroute->list, &ipv6_miniroutes );
260
261 /* Set or update address, if applicable */
262 for ( i = 0 ; i < ( sizeof ( address->s6_addr32 ) /
263 sizeof ( address->s6_addr32[0] ) ) ; i++ ) {
264 if ( ( address->s6_addr32[i] &
265 ~miniroute->prefix_mask.s6_addr32[i] ) != 0 ) {
266 memcpy ( &miniroute->address, address,
267 sizeof ( miniroute->address ) );
268 miniroute->flags |= IPV6_HAS_ADDRESS;
269 }
270 }
271 if ( miniroute->prefix_len == IPV6_MAX_PREFIX_LEN )
272 miniroute->flags |= IPV6_HAS_ADDRESS;
273
274 /* Update scope */
275 miniroute->scope = ipv6_scope ( &miniroute->address );
276
277 /* Set or update router, if applicable */
278 if ( router ) {
279 memcpy ( &miniroute->router, router,
280 sizeof ( miniroute->router ) );
281 miniroute->flags |= IPV6_HAS_ROUTER;
282 }
283
284 ipv6_dump_miniroute ( miniroute );
285 return 0;
286}
unsigned char uint8_t
Definition stdint.h:10
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
#define ENOMEM
Not enough space.
Definition errno.h:535
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static unsigned int ipv6_scope(const struct in6_addr *addr)
Determine IPv6 address scope.
Definition ipv6.c:89
static void ipv6_dump_miniroute(struct ipv6_miniroute *miniroute)
Dump IPv6 routing table entry.
Definition ipv6.c:123
static struct ipv6_miniroute * ipv6_miniroute(struct net_device *netdev, struct in6_addr *address)
Find IPv6 routing table entry for a given address.
Definition ipv6.c:193
#define IPV6_MAX_PREFIX_LEN
IPv6 maximum prefix length.
Definition ipv6.h:33
#define IPV6_DEFAULT_PREFIX_LEN
IPv6 default prefix length.
Definition ipv6.h:30
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition netdevice.h:565
unsigned int scope
Scope.
Definition ipv6.h:197

References address, ipv6_miniroute::address, assert, ENOMEM, ipv6_miniroute::flags, IPV6_DEFAULT_PREFIX_LEN, ipv6_dump_miniroute(), IPV6_HAS_ADDRESS, IPV6_HAS_ROUTER, IPV6_MAX_PREFIX_LEN, ipv6_miniroute(), ipv6_miniroutes, ipv6_scope(), ipv6_miniroute::list, list_add, list_del, memcpy(), ipv6_miniroute::netdev, netdev, netdev_get(), ipv6_miniroute::prefix_len, ipv6_miniroute::prefix_mask, ipv6_miniroute::router, ipv6_miniroute::scope, and zalloc().

Referenced by ipv6_create_routes(), and ipv6_table_okx().

◆ ipv6_del_miniroute()

void ipv6_del_miniroute ( struct ipv6_miniroute * miniroute)

Delete IPv6 minirouting table entry.

Parameters
minirouteRouting table entry

Definition at line 293 of file ipv6.c.

293 {
294
295 netdev_put ( miniroute->netdev );
296 list_del ( &miniroute->list );
297 free ( miniroute );
298}
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:576
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55

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

Referenced by ipv6_create_all_routes(), and ipv6_table_del().

◆ ipv6_route()

struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
struct in6_addr ** dest )

Perform IPv6 routing.

Parameters
scope_idDestination address scope ID (for link-local addresses)
destFinal destination address
Return values
destNext hop destination address
minirouteRouting table entry to use, or NULL if no route

Definition at line 308 of file ipv6.c.

309 {
310 struct ipv6_miniroute *miniroute;
311 struct ipv6_miniroute *chosen = NULL;
312 unsigned int best = 0;
313 unsigned int match_len;
314 unsigned int score;
315 unsigned int scope;
316
317 /* Calculate destination address scope */
318 scope = ipv6_scope ( *dest );
319
320 /* Find first usable route in routing table */
321 list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
322
323 /* Skip closed network devices */
324 if ( ! netdev_is_open ( miniroute->netdev ) )
325 continue;
326
327 /* Skip entries with no usable source address */
328 if ( ! ( miniroute->flags & IPV6_HAS_ADDRESS ) )
329 continue;
330
331 /* Skip entries with a non-matching scope ID, if
332 * destination specifies a scope ID.
333 */
334 if ( scope_id && ( miniroute->netdev->scope_id != scope_id ) )
335 continue;
336
337 /* Skip entries that are out of scope */
338 if ( miniroute->scope < scope )
339 continue;
340
341 /* Calculate match length */
342 match_len = ipv6_match_len ( miniroute, *dest );
343
344 /* If destination is on-link, then use this route */
345 if ( match_len >= miniroute->prefix_len )
346 return miniroute;
347
348 /* If destination is unicast, then skip off-link
349 * entries with no router.
350 */
351 if ( ! ( IN6_IS_ADDR_MULTICAST ( *dest ) ||
352 ( miniroute->flags & IPV6_HAS_ROUTER ) ) )
353 continue;
354
355 /* Choose best route, defined as being the route with
356 * the smallest viable scope. If two routes both have
357 * the same scope, then prefer the route with the
358 * longest match length.
359 */
360 score = ( ( ( IPV6_SCOPE_MAX + 1 - miniroute->scope ) << 8 )
361 + match_len );
362 if ( score > best ) {
363 chosen = miniroute;
364 best = score;
365 }
366 }
367
368 /* Return chosen route, if any */
369 if ( chosen ) {
370 if ( ! IN6_IS_ADDR_MULTICAST ( *dest ) )
371 *dest = &chosen->router;
372 return chosen;
373 }
374
375 return NULL;
376}
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
uint8_t scope
Scope.
Definition ena.h:7
@ IPV6_SCOPE_MAX
Maximum scope.
Definition ipv6.h:177
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition netdevice.h:662
unsigned int scope_id
Scope ID.
Definition netdevice.h:361

References dest, ipv6_miniroute::flags, IN6_IS_ADDR_MULTICAST, IPV6_HAS_ADDRESS, IPV6_HAS_ROUTER, ipv6_match_len(), ipv6_miniroutes, ipv6_scope(), IPV6_SCOPE_MAX, ipv6_miniroute::list, list_for_each_entry, ipv6_miniroute::netdev, netdev_is_open(), NULL, ipv6_miniroute::prefix_len, ipv6_miniroute::router, ipv6_miniroute::scope, scope, and net_device::scope_id.

Referenced by ipv6_netdev(), ipv6_route_okx(), and ipv6_tx().

◆ ipv6_netdev()

struct net_device * ipv6_netdev ( struct sockaddr_tcpip * st_dest)
static

Determine transmitting network device.

Parameters
st_destDestination network-layer address
Return values
netdevTransmitting network device, or NULL

Definition at line 384 of file ipv6.c.

384 {
385 struct sockaddr_in6 *sin6_dest = ( ( struct sockaddr_in6 * ) st_dest );
386 struct in6_addr *dest = &sin6_dest->sin6_addr;
387 struct ipv6_miniroute *miniroute;
388
389 /* Find routing table entry */
390 miniroute = ipv6_route ( sin6_dest->sin6_scope_id, &dest );
391 if ( ! miniroute )
392 return NULL;
393
394 return miniroute->netdev;
395}
struct ipv6_miniroute * ipv6_route(unsigned int scope_id, struct in6_addr **dest)
Perform IPv6 routing.
Definition ipv6.c:308
IP6 address structure.
Definition in.h:51
IPv6 socket address.
Definition in.h:118
struct in6_addr sin6_addr
IPv6 address.
Definition in.h:135
uint16_t sin6_scope_id
Scope ID (part of struct sockaddr_tcpip)
Definition in.h:133

References dest, ipv6_route(), ipv6_miniroute::netdev, NULL, sockaddr_in6::sin6_addr, and sockaddr_in6::sin6_scope_id.

◆ ipv6_check_options()

int ipv6_check_options ( struct ipv6_header * iphdr,
struct ipv6_options_header * options,
size_t len )
static

Check that received options can be safely ignored.

Parameters
iphdrIPv6 header
optionsOptions extension header
lenMaximum length of header
Return values
rcReturn status code

Definition at line 405 of file ipv6.c.

407 {
408 struct ipv6_option *option = options->options;
409 struct ipv6_option *end = ( ( ( void * ) options ) + len );
410
411 while ( option < end ) {
412 if ( ! IPV6_CAN_IGNORE_OPT ( option->type ) ) {
413 DBGC ( ipv6col ( &iphdr->src ), "IPv6 unrecognised "
414 "option type %#02x:\n", option->type );
415 DBGC_HDA ( ipv6col ( &iphdr->src ), 0,
416 options, len );
417 return -ENOTSUP_OPT;
418 }
419 if ( option->type == IPV6_OPT_PAD1 ) {
420 option = ( ( ( void * ) option ) + 1 );
421 } else {
422 option = ( ( ( void * ) option->value ) + option->len );
423 }
424 }
425 return 0;
426}
static int options
Definition 3c515.c:286
ring len
Length.
Definition dwmac.h:226
#define DBGC_HDA(...)
Definition compiler.h:506
static uint32_t ipv6col(struct in6_addr *in)
Determine debugging colour for IPv6 debug messages.
Definition ipv6.c:79
#define ENOTSUP_OPT
Definition ipv6.c:56
@ IPV6_OPT_PAD1
Pad1.
Definition ipv6.h:72
#define IPV6_CAN_IGNORE_OPT(type)
Test if IPv6 option can be safely ignored.
Definition ipv6.h:78
uint32_t end
Ending offset.
Definition netvsc.h:7
An IPv4 packet header.
Definition ip.h:36
struct in_addr src
Definition ip.h:45
IPv6 type-length-value options.
Definition ipv6.h:60
A long option, as used for getopt_long()
Definition getopt.h:25

References DBGC, DBGC_HDA, end, ENOTSUP_OPT, IPV6_CAN_IGNORE_OPT, IPV6_OPT_PAD1, ipv6col(), len, options, and iphdr::src.

Referenced by ipv6_rx().

◆ ipv6_is_fragment()

int ipv6_is_fragment ( struct fragment * fragment,
struct io_buffer * iobuf,
size_t hdrlen )
static

Check if fragment matches fragment reassembly buffer.

Parameters
fragmentFragment reassembly buffer
iobufI/O buffer
hdrlenLength of non-fragmentable potion of I/O buffer
Return values
is_fragmentFragment matches this reassembly buffer

Definition at line 436 of file ipv6.c.

437 {
438 struct ipv6_header *frag_iphdr = fragment->iobuf->data;
439 struct ipv6_fragment_header *frag_fhdr =
441 sizeof ( *frag_fhdr ) );
442 struct ipv6_header *iphdr = iobuf->data;
443 struct ipv6_fragment_header *fhdr =
444 ( iobuf->data + hdrlen - sizeof ( *fhdr ) );
445
446 return ( ( memcmp ( &iphdr->src, &frag_iphdr->src,
447 sizeof ( iphdr->src ) ) == 0 ) &&
448 ( fhdr->ident == frag_fhdr->ident ) );
449}
A fragment reassembly buffer.
Definition fragment.h:22
struct io_buffer * iobuf
Reassembled packet.
Definition fragment.h:26
size_t hdrlen
Length of non-fragmentable portion of reassembled packet.
Definition fragment.h:28
void * data
Start of data.
Definition iobuf.h:53
IPv6 fragment header.
Definition ipv6.h:101
uint32_t ident
Identification.
Definition ipv6.h:107
IPv6 header.
Definition ipv6.h:36
struct in6_addr src
Source address.
Definition ipv6.h:46

References io_buffer::data, fragment::hdrlen, ipv6_fragment_header::ident, fragment::iobuf, memcmp(), iphdr::src, and ipv6_header::src.

◆ ipv6_fragment_offset()

size_t ipv6_fragment_offset ( struct io_buffer * iobuf,
size_t hdrlen )
static

Get fragment offset.

Parameters
iobufI/O buffer
hdrlenLength of non-fragmentable potion of I/O buffer
Return values
offsetOffset

Definition at line 458 of file ipv6.c.

458 {
459 struct ipv6_fragment_header *fhdr =
460 ( iobuf->data + hdrlen - sizeof ( *fhdr ) );
461
462 return ( ntohs ( fhdr->offset_more ) & IPV6_MASK_OFFSET );
463}
#define ntohs(value)
Definition byteswap.h:137
#define IPV6_MASK_OFFSET
Fragment offset mask.
Definition ipv6.h:111
uint16_t offset_more
Fragment offset (13 bits), reserved, more fragments (1 bit)
Definition ipv6.h:105

References io_buffer::data, IPV6_MASK_OFFSET, ntohs, and ipv6_fragment_header::offset_more.

◆ ipv6_more_fragments()

int ipv6_more_fragments ( struct io_buffer * iobuf,
size_t hdrlen )
static

Check if more fragments exist.

Parameters
iobufI/O buffer
hdrlenLength of non-fragmentable potion of I/O buffer
Return values
more_fragsMore fragments exist

Definition at line 472 of file ipv6.c.

472 {
473 struct ipv6_fragment_header *fhdr =
474 ( iobuf->data + hdrlen - sizeof ( *fhdr ) );
475
476 return ( fhdr->offset_more & htons ( IPV6_MASK_MOREFRAGS ) );
477}
#define htons(value)
Definition byteswap.h:136
#define IPV6_MASK_MOREFRAGS
More fragments.
Definition ipv6.h:114

References io_buffer::data, htons, IPV6_MASK_MOREFRAGS, and ipv6_fragment_header::offset_more.

◆ ipv6_pshdr_chksum()

uint16_t ipv6_pshdr_chksum ( struct ipv6_header * iphdr,
size_t len,
int next_header,
uint16_t csum )
static

Calculate IPv6 pseudo-header checksum.

Parameters
iphdrIPv6 header
lenPayload length
next_headerNext header type
csumExisting checksum
Return values
csumUpdated checksum

Definition at line 497 of file ipv6.c.

498 {
499 struct ipv6_pseudo_header pshdr;
500
501 /* Build pseudo-header */
502 memcpy ( &pshdr.src, &iphdr->src, sizeof ( pshdr.src ) );
503 memcpy ( &pshdr.dest, &iphdr->dest, sizeof ( pshdr.dest ) );
504 pshdr.len = htonl ( len );
505 memset ( pshdr.zero, 0, sizeof ( pshdr.zero ) );
506 pshdr.next_header = next_header;
507
508 /* Update the checksum value */
509 return tcpip_continue_chksum ( csum, &pshdr, sizeof ( pshdr ) );
510}
#define htonl(value)
Definition byteswap.h:134
void * memset(void *dest, int character, size_t len) __nonnull
struct in_addr dest
Definition ip.h:46
IPv6 pseudo-header.
Definition ipv6.h:149
uint8_t next_header
Next header.
Definition ipv6.h:159
uint16_t tcpip_continue_chksum(uint16_t partial, const void *data, size_t len)
Calculate continued TCP/IP checkum.
Definition x86_tcpip.c:46

References iphdr::dest, ipv6_pseudo_header::dest, htonl, ipv6_pseudo_header::len, len, memcpy(), memset(), ipv6_pseudo_header::next_header, iphdr::src, ipv6_pseudo_header::src, tcpip_continue_chksum(), and ipv6_pseudo_header::zero.

Referenced by ipv6_rx(), and ipv6_tx().

◆ ipv6_tx()

int ipv6_tx ( struct io_buffer * iobuf,
struct tcpip_protocol * tcpip_protocol,
struct sockaddr_tcpip * st_src,
struct sockaddr_tcpip * st_dest,
struct net_device * netdev,
uint16_t * trans_csum )
static

Transmit IPv6 packet.

Parameters
iobufI/O buffer
tcpipTransport-layer protocol
st_srcSource network-layer address
st_destDestination network-layer address
netdevNetwork device to use if no route found, or NULL
trans_csumTransport-layer checksum to complete, or NULL
Return values
rcStatus

This function expects a transport-layer segment and prepends the IPv6 header

Definition at line 526 of file ipv6.c.

531 {
532 struct sockaddr_in6 *sin6_src = ( ( struct sockaddr_in6 * ) st_src );
533 struct sockaddr_in6 *sin6_dest = ( ( struct sockaddr_in6 * ) st_dest );
534 struct ipv6_miniroute *miniroute;
535 struct ipv6_header *iphdr;
536 struct in6_addr *src = NULL;
537 struct in6_addr *next_hop;
538 uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
539 const void *ll_dest;
540 size_t len;
541 int rc;
542
543 /* Update statistics */
544 ipv6_stats.out_requests++;
545
546 /* Fill up the IPv6 header, except source address */
547 len = iob_len ( iobuf );
548 iphdr = iob_push ( iobuf, sizeof ( *iphdr ) );
549 memset ( iphdr, 0, sizeof ( *iphdr ) );
550 iphdr->ver_tc_label = htonl ( IPV6_VER );
551 iphdr->len = htons ( len );
552 iphdr->next_header = tcpip_protocol->tcpip_proto;
553 iphdr->hop_limit = IPV6_HOP_LIMIT;
554 memcpy ( &iphdr->dest, &sin6_dest->sin6_addr, sizeof ( iphdr->dest ) );
555
556 /* Use routing table to identify next hop and transmitting netdev */
557 next_hop = &iphdr->dest;
558 if ( ( miniroute = ipv6_route ( sin6_dest->sin6_scope_id,
559 &next_hop ) ) != NULL ) {
560 src = &miniroute->address;
561 netdev = miniroute->netdev;
562 }
563 if ( ! netdev ) {
564 DBGC ( ipv6col ( &iphdr->dest ), "IPv6 has no route to %s\n",
565 inet6_ntoa ( &iphdr->dest ) );
566 ipv6_stats.out_no_routes++;
567 rc = -ENETUNREACH;
568 goto err;
569 }
570 if ( sin6_src && ! IN6_IS_ADDR_UNSPECIFIED ( &sin6_src->sin6_addr ) )
571 src = &sin6_src->sin6_addr;
572 if ( src )
573 memcpy ( &iphdr->src, src, sizeof ( iphdr->src ) );
574
575 /* Fix up checksums */
576 if ( trans_csum ) {
577 *trans_csum = ipv6_pshdr_chksum ( iphdr, len,
579 *trans_csum );
580 if ( ! *trans_csum )
581 *trans_csum = tcpip_protocol->zero_csum;
582 }
583
584 /* Print IPv6 header for debugging */
585 DBGC2 ( ipv6col ( &iphdr->dest ), "IPv6 TX %s->",
586 inet6_ntoa ( &iphdr->src ) );
587 DBGC2 ( ipv6col ( &iphdr->dest ), "%s len %zd next %d\n",
588 inet6_ntoa ( &iphdr->dest ), len, iphdr->next_header );
589
590 /* Calculate link-layer destination address, if possible */
591 if ( IN6_IS_ADDR_MULTICAST ( next_hop ) ) {
592 /* Multicast address */
593 ipv6_stats.out_mcast_pkts++;
594 if ( ( rc = netdev->ll_protocol->mc_hash ( AF_INET6, next_hop,
595 ll_dest_buf ) ) !=0){
596 DBGC ( ipv6col ( &iphdr->dest ), "IPv6 could not hash "
597 "multicast %s: %s\n", inet6_ntoa ( next_hop ),
598 strerror ( rc ) );
599 goto err;
600 }
601 ll_dest = ll_dest_buf;
602 } else {
603 /* Unicast address */
604 ll_dest = NULL;
605 }
606
607 /* Update statistics */
608 ipv6_stats.out_transmits++;
609 ipv6_stats.out_octets += iob_len ( iobuf );
610
611 /* Hand off to link layer (via NDP if applicable) */
612 if ( ll_dest ) {
613 if ( ( rc = net_tx ( iobuf, netdev, &ipv6_protocol, ll_dest,
614 netdev->ll_addr ) ) != 0 ) {
615 DBGC ( ipv6col ( &iphdr->dest ), "IPv6 could not "
616 "transmit packet via %s: %s\n",
617 netdev->name, strerror ( rc ) );
618 return rc;
619 }
620 } else {
621 if ( ( rc = ndp_tx ( iobuf, netdev, next_hop,
622 &iphdr->src ) ) != 0 ) {
623 DBGC ( ipv6col ( &iphdr->dest ), "IPv6 could not "
624 "transmit packet via %s: %s\n",
625 netdev->name, strerror ( rc ) );
626 return rc;
627 }
628 }
629
630 return 0;
631
632 err:
633 free_iob ( iobuf );
634 return rc;
635}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
static const void * src
Definition string.h:48
#define AF_INET6
IPv6 Internet addresses.
Definition socket.h:65
#define DBGC2(...)
Definition compiler.h:522
#define ENETUNREACH
Network unreachable.
Definition errno.h:489
#define IN6_IS_ADDR_UNSPECIFIED(addr)
Definition in.h:62
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
#define iob_push(iobuf, len)
Definition iobuf.h:89
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
static struct ip_statistics ipv6_stats
IPv6 statistics.
Definition ipv6.c:64
static uint16_t ipv6_pshdr_chksum(struct ipv6_header *iphdr, size_t len, int next_header, uint16_t csum)
Calculate IPv6 pseudo-header checksum.
Definition ipv6.c:497
#define IPV6_HOP_LIMIT
IPv6 maximum hop limit.
Definition ipv6.h:27
#define IPV6_VER
IPv6 version.
Definition ipv6.h:21
static int ndp_tx(struct io_buffer *iobuf, struct net_device *netdev, const void *net_dest, const void *net_source)
Transmit packet, determining link-layer address via NDP.
Definition ndp.h:195
int net_tx(struct io_buffer *iobuf, struct net_device *netdev, struct net_protocol *net_protocol, const void *ll_dest, const void *ll_source)
Transmit network-layer packet.
Definition netdevice.c:1074
#define MAX_LL_ADDR_LEN
Maximum length of a link-layer address.
Definition netdevice.h:37
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
uint16_t len
Definition ip.h:39
A transport-layer protocol of the TCP/IP stack (eg.
Definition tcpip.h:105
uint8_t tcpip_proto
Transport-layer protocol number.
Definition tcpip.h:135
uint16_t zero_csum
Preferred zero checksum value.
Definition tcpip.h:129

References ipv6_miniroute::address, AF_INET6, DBGC, DBGC2, iphdr::dest, ENETUNREACH, free_iob(), htonl, htons, IN6_IS_ADDR_MULTICAST, IN6_IS_ADDR_UNSPECIFIED, inet6_ntoa(), iob_len(), iob_push, IPV6_HOP_LIMIT, ipv6_pshdr_chksum(), ipv6_route(), ipv6_stats, IPV6_VER, ipv6col(), iphdr::len, len, MAX_LL_ADDR_LEN, memcpy(), memset(), ndp_tx(), net_tx(), ipv6_miniroute::netdev, netdev, NULL, rc, sockaddr_in6::sin6_addr, sockaddr_in6::sin6_scope_id, iphdr::src, src, strerror(), tcpip_protocol::tcpip_proto, and tcpip_protocol::zero_csum.

◆ ipv6_rx()

int ipv6_rx ( struct io_buffer * iobuf,
struct net_device * netdev,
const void *ll_dest __unused,
const void *ll_source __unused,
unsigned int flags __unused )
static

Process incoming IPv6 packets.

Parameters
iobufI/O buffer
netdevNetwork device
ll_destLink-layer destination address
ll_sourceLink-layer destination source
flagsPacket flags
Return values
rcReturn status code

This function expects an IPv6 network datagram. It processes the headers and sends it to the transport layer.

Definition at line 650 of file ipv6.c.

653 {
654 struct ipv6_header *iphdr = iobuf->data;
656 union {
657 struct sockaddr_in6 sin6;
658 struct sockaddr_tcpip st;
659 } src, dest;
660 uint16_t pshdr_csum;
661 size_t len;
662 size_t hdrlen;
663 size_t extlen;
664 int this_header;
665 int next_header;
666 int rc;
667
668 /* Update statistics */
669 ipv6_stats.in_receives++;
670 ipv6_stats.in_octets += iob_len ( iobuf );
671 if ( flags & LL_BROADCAST ) {
672 ipv6_stats.in_bcast_pkts++;
673 } else if ( flags & LL_MULTICAST ) {
674 ipv6_stats.in_mcast_pkts++;
675 }
676
677 /* Sanity check the IPv6 header */
678 if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
679 DBGC ( ipv6col ( &iphdr->src ), "IPv6 packet too short at %zd "
680 "bytes (min %zd bytes)\n", iob_len ( iobuf ),
681 sizeof ( *iphdr ) );
682 rc = -EINVAL_LEN;
683 goto err_header;
684 }
685 if ( ( iphdr->ver_tc_label & htonl ( IPV6_MASK_VER ) ) !=
686 htonl ( IPV6_VER ) ) {
687 DBGC ( ipv6col ( &iphdr->src ), "IPv6 version %#08x not "
688 "supported\n", ntohl ( iphdr->ver_tc_label ) );
689 rc = -ENOTSUP_VER;
690 goto err_header;
691 }
692
693 /* Truncate packet to specified length */
694 len = ntohs ( iphdr->len );
695 if ( len > iob_len ( iobuf ) ) {
696 DBGC ( ipv6col ( &iphdr->src ), "IPv6 length too long at %zd "
697 "bytes (packet is %zd bytes)\n", len, iob_len ( iobuf ));
698 ipv6_stats.in_truncated_pkts++;
699 rc = -EINVAL_LEN;
700 goto err_other;
701 }
702 iob_unput ( iobuf, ( iob_len ( iobuf ) - len - sizeof ( *iphdr ) ) );
703 hdrlen = sizeof ( *iphdr );
704
705 /* Print IPv6 header for debugging */
706 DBGC2 ( ipv6col ( &iphdr->src ), "IPv6 RX %s<-",
707 inet6_ntoa ( &iphdr->dest ) );
708 DBGC2 ( ipv6col ( &iphdr->src ), "%s len %zd next %d\n",
709 inet6_ntoa ( &iphdr->src ), len, iphdr->next_header );
710
711 /* Discard unicast packets not destined for us */
712 if ( ( ! ( flags & LL_MULTICAST ) ) &&
713 ( ! ipv6_has_addr ( netdev, &iphdr->dest ) ) ) {
714 DBGC ( ipv6col ( &iphdr->src ), "IPv6 discarding non-local "
715 "unicast packet for %s\n", inet6_ntoa ( &iphdr->dest ) );
716 ipv6_stats.in_addr_errors++;
717 rc = -EPIPE;
718 goto err_other;
719 }
720
721 /* Process any extension headers */
722 next_header = iphdr->next_header;
723 while ( 1 ) {
724
725 /* Extract extension header */
726 this_header = next_header;
727 ext = ( iobuf->data + hdrlen );
728 extlen = sizeof ( ext->pad );
729 if ( iob_len ( iobuf ) < ( hdrlen + extlen ) ) {
730 DBGC ( ipv6col ( &iphdr->src ), "IPv6 too short for "
731 "extension header type %d at %zd bytes (min "
732 "%zd bytes)\n", this_header,
733 ( iob_len ( iobuf ) - hdrlen ), extlen );
734 rc = -EINVAL_LEN;
735 goto err_header;
736 }
737
738 /* Determine size of extension header (if applicable) */
739 if ( ( this_header == IPV6_HOPBYHOP ) ||
740 ( this_header == IPV6_DESTINATION ) ||
741 ( this_header == IPV6_ROUTING ) ) {
742 /* Length field is present */
743 extlen += ext->common.len;
744 } else if ( this_header == IPV6_FRAGMENT ) {
745 /* Length field is reserved and ignored (RFC2460) */
746 } else {
747 /* Not an extension header; assume rest is payload */
748 break;
749 }
750 if ( iob_len ( iobuf ) < ( hdrlen + extlen ) ) {
751 DBGC ( ipv6col ( &iphdr->src ), "IPv6 too short for "
752 "extension header type %d at %zd bytes (min "
753 "%zd bytes)\n", this_header,
754 ( iob_len ( iobuf ) - hdrlen ), extlen );
755 rc = -EINVAL_LEN;
756 goto err_header;
757 }
758 hdrlen += extlen;
759 next_header = ext->common.next_header;
760 DBGC2 ( ipv6col ( &iphdr->src ), "IPv6 RX %s<-",
761 inet6_ntoa ( &iphdr->dest ) );
762 DBGC2 ( ipv6col ( &iphdr->src ), "%s ext type %d len %zd next "
763 "%d\n", inet6_ntoa ( &iphdr->src ), this_header,
764 extlen, next_header );
765
766 /* Process this extension header */
767 if ( ( this_header == IPV6_HOPBYHOP ) ||
768 ( this_header == IPV6_DESTINATION ) ) {
769
770 /* Check that all options can be ignored */
771 if ( ( rc = ipv6_check_options ( iphdr, &ext->options,
772 extlen ) ) != 0 )
773 goto err_header;
774
775 } else if ( this_header == IPV6_FRAGMENT ) {
776
777 /* Reassemble fragments */
778 iobuf = fragment_reassemble ( &ipv6_reassembler, iobuf,
779 &hdrlen );
780 if ( ! iobuf )
781 return 0;
782 iphdr = iobuf->data;
783 }
784 }
785
786 /* Construct socket address, calculate pseudo-header checksum,
787 * and hand off to transport layer
788 */
789 memset ( &src, 0, sizeof ( src ) );
790 src.sin6.sin6_family = AF_INET6;
791 memcpy ( &src.sin6.sin6_addr, &iphdr->src,
792 sizeof ( src.sin6.sin6_addr ) );
793 src.sin6.sin6_scope_id = netdev->scope_id;
794 memset ( &dest, 0, sizeof ( dest ) );
795 dest.sin6.sin6_family = AF_INET6;
796 memcpy ( &dest.sin6.sin6_addr, &iphdr->dest,
797 sizeof ( dest.sin6.sin6_addr ) );
798 dest.sin6.sin6_scope_id = netdev->scope_id;
799 iob_pull ( iobuf, hdrlen );
800 pshdr_csum = ipv6_pshdr_chksum ( iphdr, iob_len ( iobuf ),
801 next_header, TCPIP_EMPTY_CSUM );
802 if ( ( rc = tcpip_rx ( iobuf, netdev, next_header, &src.st, &dest.st,
803 pshdr_csum, &ipv6_stats ) ) != 0 ) {
804 DBGC ( ipv6col ( &src.sin6.sin6_addr ), "IPv6 received packet "
805 "rejected by stack: %s\n", strerror ( rc ) );
806 return rc;
807 }
808
809 return 0;
810
811 err_header:
812 ipv6_stats.in_hdr_errors++;
813 err_other:
814 free_iob ( iobuf );
815 return rc;
816}
unsigned short uint16_t
Definition stdint.h:11
uint16_t ext
Extended status.
Definition ena.h:9
uint8_t flags
Flags.
Definition ena.h:7
struct io_buffer * fragment_reassemble(struct fragment_reassembler *fragments, struct io_buffer *iobuf, size_t *hdrlen)
Reassemble packet.
Definition fragment.c:89
#define EPIPE
Broken pipe.
Definition errno.h:620
#define TCPIP_EMPTY_CSUM
Empty checksum value.
Definition tcpip.h:58
#define iob_pull(iobuf, len)
Definition iobuf.h:107
#define iob_unput(iobuf, len)
Definition iobuf.h:140
#define EINVAL_LEN
Definition ipv6.c:47
static int ipv6_check_options(struct ipv6_header *iphdr, struct ipv6_options_header *options, size_t len)
Check that received options can be safely ignored.
Definition ipv6.c:405
int ipv6_has_addr(struct net_device *netdev, struct in6_addr *addr)
Check if network device has a specific IPv6 address.
Definition ipv6.c:142
#define ENOTSUP_VER
Definition ipv6.c:50
static struct fragment_reassembler ipv6_reassembler
Fragment reassembler.
Definition ipv6.c:480
@ IPV6_HOPBYHOP
IPv6 hop-by-hop options header type.
Definition ipv6.h:137
@ IPV6_FRAGMENT
IPv6 fragment header type.
Definition ipv6.h:141
@ IPV6_DESTINATION
IPv6 destination options header type.
Definition ipv6.h:145
@ IPV6_ROUTING
IPv6 routing header type.
Definition ipv6.h:139
#define IPV6_MASK_VER
IPv6 version mask.
Definition ipv6.h:24
#define LL_MULTICAST
Packet is a multicast (including broadcast) packet.
Definition netdevice.h:106
#define LL_BROADCAST
Packet is a broadcast packet.
Definition netdevice.h:109
struct sockaddr_in6 sin6
Definition syslog.c:60
struct sockaddr_tcpip st
Definition syslog.c:58
int tcpip_rx(struct io_buffer *iobuf, struct net_device *netdev, uint8_t tcpip_proto, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum, struct ip_statistics *stats)
Process a received TCP/IP packet.
Definition tcpip.c:41
IPv6 extension header.
Definition ipv6.h:117

References __unused, AF_INET6, io_buffer::data, DBGC, DBGC2, dest, iphdr::dest, EINVAL_LEN, ENOTSUP_VER, EPIPE, ext, flags, fragment_reassemble(), free_iob(), htonl, inet6_ntoa(), iob_len(), iob_pull, iob_unput, ipv6_check_options(), IPV6_DESTINATION, IPV6_FRAGMENT, ipv6_has_addr(), IPV6_HOPBYHOP, IPV6_MASK_VER, ipv6_pshdr_chksum(), ipv6_reassembler, IPV6_ROUTING, ipv6_stats, IPV6_VER, ipv6col(), iphdr::len, len, LL_BROADCAST, LL_MULTICAST, memcpy(), memset(), netdev, ntohl, ntohs, rc, sin6, iphdr::src, src, st, strerror(), TCPIP_EMPTY_CSUM, and tcpip_rx().

◆ inet6_aton()

int inet6_aton ( const char * string,
struct in6_addr * in )

Parse IPv6 address.

Parameters
stringIPv6 address string
Return values
inIPv6 address to fill in
rcReturn status code

Definition at line 825 of file ipv6.c.

825 {
826 uint16_t *word = in->s6_addr16;
827 uint16_t *end = ( word + ( sizeof ( in->s6_addr16 ) /
828 sizeof ( in->s6_addr16[0] ) ) );
829 uint16_t *pad = NULL;
830 const char *nptr = string;
831 char *endptr;
832 unsigned long value;
833 size_t pad_len;
834 size_t move_len;
835
836 /* Parse string */
837 while ( 1 ) {
838
839 /* Parse current word */
840 value = strtoul ( nptr, &endptr, 16 );
841 if ( value > 0xffff ) {
842 DBG ( "IPv6 invalid word value %#lx in \"%s\"\n",
843 value, string );
844 return -EINVAL;
845 }
846 *(word++) = htons ( value );
847
848 /* Parse separator */
849 if ( ! *endptr )
850 break;
851 if ( *endptr != ':' ) {
852 DBG ( "IPv6 invalid separator '%c' in \"%s\"\n",
853 *endptr, string );
854 return -EINVAL;
855 }
856 if ( ( endptr == nptr ) && ( nptr != string ) ) {
857 if ( pad ) {
858 DBG ( "IPv6 invalid multiple \"::\" in "
859 "\"%s\"\n", string );
860 return -EINVAL;
861 }
862 pad = word;
863 }
864 nptr = ( endptr + 1 );
865
866 /* Check for overrun */
867 if ( word == end ) {
868 DBG ( "IPv6 too many words in \"%s\"\n", string );
869 return -EINVAL;
870 }
871 }
872
873 /* Insert padding if specified */
874 if ( pad ) {
875 move_len = ( ( ( void * ) word ) - ( ( void * ) pad ) );
876 pad_len = ( ( ( void * ) end ) - ( ( void * ) word ) );
877 memmove ( ( ( ( void * ) pad ) + pad_len ), pad, move_len );
878 memset ( pad, 0, pad_len );
879 } else if ( word != end ) {
880 DBG ( "IPv6 underlength address \"%s\"\n", string );
881 return -EINVAL;
882 }
883
884 return 0;
885}
u32 pad[9]
Padding.
Definition ar9003_mac.h:23
pseudo_bit_t value[0x00020]
Definition arbel.h:2
long pad_len
Definition bigint.h:31
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define EINVAL
Invalid argument.
Definition errno.h:429
void * memmove(void *dest, const void *src, size_t len) __nonnull
uint32_t string
Definition multiboot.h:2
unsigned short word
Definition smc9000.h:39
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition string.c:485

References DBG, EINVAL, end, htons, in, memmove(), memset(), NULL, pad, pad_len, string, strtoul(), and value.

Referenced by inet6_aton_fail_okx(), inet6_aton_okx(), ipv6_route_okx(), ipv6_sock_aton(), ipv6_table_okx(), and parse_ipv6_setting().

◆ inet6_ntoa()

char * inet6_ntoa ( const struct in6_addr * in)

Convert IPv6 address to standard notation.

Parameters
inIPv6 address
Return values
stringIPv6 address string in canonical format

RFC5952 defines the canonical format for IPv6 textual representation.

Definition at line 895 of file ipv6.c.

895 {
896 static char buf[41]; /* ":xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx" */
897 char *out = buf;
898 char *longest_start = NULL;
899 char *start = NULL;
900 int longest_len = 1;
901 int len = 0;
902 char *dest;
903 unsigned int i;
905
906 /* Format address, keeping track of longest run of zeros */
907 for ( i = 0 ; i < ( sizeof ( in->s6_addr16 ) /
908 sizeof ( in->s6_addr16[0] ) ) ; i++ ) {
909 value = ntohs ( in->s6_addr16[i] );
910 if ( value == 0 ) {
911 if ( len++ == 0 )
912 start = out;
913 if ( len > longest_len ) {
914 longest_start = start;
915 longest_len = len;
916 }
917 } else {
918 len = 0;
919 }
920 out += sprintf ( out, ":%x", value );
921 }
922
923 /* Abbreviate longest run of zeros, if applicable */
924 if ( longest_start ) {
925 dest = strcpy ( ( longest_start + 1 ),
926 ( longest_start + ( 2 * longest_len ) ) );
927 if ( dest[0] == '\0' )
928 dest[1] = '\0';
929 dest[0] = ':';
930 }
931 return ( ( longest_start == buf ) ? buf : ( buf + 1 ) );
932}
__be32 out[4]
Definition CIB_PRM.h:8
uint32_t start
Starting offset.
Definition netvsc.h:1
#define sprintf(buf, fmt,...)
Write a formatted string to a buffer.
Definition stdio.h:37
char * strcpy(char *dest, const char *src)
Copy string.
Definition string.c:347

References dest, in, len, ntohs, NULL, out, sprintf, start, strcpy(), and value.

Referenced by dhcpv6_rx(), format_ipv6_setting(), inet6_aton_okx(), inet6_ntoa_okx(), ipv6_dump_miniroute(), ipv6_ntoa(), ipv6_route_okx(), ipv6_rx(), ipv6_sock_ntoa(), ipv6_tx(), ndp_prefix_fetch_ip6(), ndp_rx_neighbour_advertisement_ll_target(), ndp_rx_neighbour_solicitation_ll_source(), ndp_rx_router_advertisement_ll_source(), ndp_rx_router_advertisement_prefix(), and route_ipv6_print().

◆ ipv6_ntoa()

const char * ipv6_ntoa ( const void * net_addr)
static

Transcribe IPv6 address.

Parameters
net_addrIPv6 address
Return values
stringIPv6 address in standard notation

Definition at line 941 of file ipv6.c.

941 {
942 return inet6_ntoa ( net_addr );
943}

References inet6_ntoa().

◆ ipv6_sock_ntoa()

const char * ipv6_sock_ntoa ( struct sockaddr * sa)
static

Transcribe IPv6 socket address.

Parameters
saSocket address
Return values
stringSocket address in standard notation

Definition at line 951 of file ipv6.c.

951 {
952 static char buf[ 39 /* "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx" */ +
953 1 /* "%" */ + NETDEV_NAME_LEN + 1 /* NUL */ ];
954 struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) sa );
955 struct in6_addr *in = &sin6->sin6_addr;
956 struct net_device *netdev;
957 const char *netdev_name;
958
959 /* Identify network device, if applicable */
961 netdev = find_netdev_by_scope_id ( sin6->sin6_scope_id );
962 netdev_name = ( netdev ? netdev->name : "UNKNOWN" );
963 } else {
964 netdev_name = NULL;
965 }
966
967 /* Format socket address */
968 snprintf ( buf, sizeof ( buf ), "%s%s%s", inet6_ntoa ( in ),
969 ( netdev_name ? "%" : "" ),
970 ( netdev_name ? netdev_name : "" ) );
971 return buf;
972}
struct net_device * find_netdev_by_scope_id(unsigned int scope_id)
Get network device by scope ID.
Definition netdevice.c:1011
#define NETDEV_NAME_LEN
Maximum length of a network device name.
Definition netdevice.h:341
struct sockaddr sa
Definition syslog.c:57
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383

References find_netdev_by_scope_id(), in, IN6_IS_ADDR_LINKLOCAL, IN6_IS_ADDR_MULTICAST, inet6_ntoa(), netdev, NETDEV_NAME_LEN, NULL, sa, sin6, and snprintf().

◆ ipv6_sock_aton()

int ipv6_sock_aton ( const char * string,
struct sockaddr * sa )
static

Parse IPv6 socket address.

Parameters
stringSocket address string
saSocket address to fill in
Return values
rcReturn status code

Definition at line 981 of file ipv6.c.

981 {
982 struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) sa );
983 struct in6_addr in;
984 struct net_device *netdev;
985 size_t len;
986 char *tmp;
987 char *in_string;
988 char *netdev_string;
989 int rc;
990
991 /* Create modifiable copy of string */
992 tmp = strdup ( string );
993 if ( ! tmp ) {
994 rc = -ENOMEM;
995 goto err_alloc;
996 }
997 in_string = tmp;
998
999 /* Strip surrounding "[...]", if present */
1000 len = strlen ( in_string );
1001 if ( ( in_string[0] == '[' ) && ( in_string[ len - 1 ] == ']' ) ) {
1002 in_string[ len - 1 ] = '\0';
1003 in_string++;
1004 }
1005
1006 /* Split at network device name, if present */
1007 netdev_string = strchr ( in_string, '%' );
1008 if ( netdev_string )
1009 *(netdev_string++) = '\0';
1010
1011 /* Parse IPv6 address portion */
1012 if ( ( rc = inet6_aton ( in_string, &in ) ) != 0 )
1013 goto err_inet6_aton;
1014
1015 /* Parse scope ID, if applicable */
1016 if ( netdev_string ) {
1017
1018 /* Parse explicit network device name, if present */
1019 netdev = find_netdev ( netdev_string );
1020 if ( ! netdev ) {
1021 rc = -ENODEV;
1022 goto err_find_netdev;
1023 }
1024 sin6->sin6_scope_id = netdev->scope_id;
1025
1026 } else if ( IN6_IS_ADDR_LINKLOCAL ( &in ) ||
1027 IN6_IS_ADDR_MULTICAST ( &in ) ) {
1028
1029 /* If no network device is explicitly specified for a
1030 * link-local or multicast address, default to using
1031 * "netX" (if existent).
1032 */
1034 if ( netdev )
1035 sin6->sin6_scope_id = netdev->scope_id;
1036 }
1037
1038 /* Copy IPv6 address portion to socket address */
1039 memcpy ( &sin6->sin6_addr, &in, sizeof ( sin6->sin6_addr ) );
1040
1041 err_find_netdev:
1042 err_inet6_aton:
1043 free ( tmp );
1044 err_alloc:
1045 return rc;
1046}
#define ENODEV
No such device.
Definition errno.h:510
int inet6_aton(const char *string, struct in6_addr *in)
Parse IPv6 address.
Definition ipv6.c:825
unsigned long tmp
Definition linux_pci.h:65
struct net_device * last_opened_netdev(void)
Get most recently opened network device.
Definition netdevice.c:1048
struct net_device * find_netdev(const char *name)
Get network device by name.
Definition netdevice.c:989
char * strchr(const char *src, int character)
Find character within a string.
Definition string.c:272
char * strdup(const char *src)
Duplicate string.
Definition string.c:394
size_t strlen(const char *src)
Get length of string.
Definition string.c:244

References ENODEV, ENOMEM, find_netdev(), free, in, IN6_IS_ADDR_LINKLOCAL, IN6_IS_ADDR_MULTICAST, inet6_aton(), last_opened_netdev(), len, memcpy(), netdev, rc, sa, sin6, strchr(), strdup(), strlen(), and tmp.

◆ parse_ipv6_setting()

int parse_ipv6_setting ( const struct setting_type *type __unused,
const char * value,
void * buf,
size_t len )

Parse IPv6 address setting value.

Parameters
typeSetting type
valueFormatted setting value
bufBuffer to contain raw value
lenLength of buffer
Return values
lenLength of raw value, or negative error

Definition at line 1083 of file ipv6.c.

1084 {
1085 struct in6_addr ipv6;
1086 int rc;
1087
1088 /* Parse IPv6 address */
1089 if ( ( rc = inet6_aton ( value, &ipv6 ) ) != 0 )
1090 return rc;
1091
1092 /* Copy to buffer */
1093 if ( len > sizeof ( ipv6 ) )
1094 len = sizeof ( ipv6 );
1095 memcpy ( buf, &ipv6, len );
1096
1097 return ( sizeof ( ipv6 ) );
1098}

References __unused, inet6_aton(), len, memcpy(), rc, type, and value.

◆ format_ipv6_setting()

int format_ipv6_setting ( const struct setting_type *type __unused,
const void * raw,
size_t raw_len,
char * buf,
size_t len )

Format IPv6 address setting value.

Parameters
typeSetting type
rawRaw setting value
raw_lenLength of raw setting value
bufBuffer to contain formatted value
lenLength of buffer
Return values
lenLength of formatted value, or negative error

Definition at line 1110 of file ipv6.c.

1112 {
1113 const struct in6_addr *ipv6 = raw;
1114
1115 if ( raw_len < sizeof ( *ipv6 ) )
1116 return -EINVAL;
1117 return snprintf ( buf, len, "%s", inet6_ntoa ( ipv6 ) );
1118}
__be32 raw[7]
Definition CIB_PRM.h:0
static size_t raw_len
Definition base16.h:54

References __unused, EINVAL, inet6_ntoa(), len, raw, raw_len, snprintf(), and type.

◆ __setting() [1/3]

const struct setting ip6_setting __setting ( SETTING_IP6 ,
ip6  )

IPv6 address setting.

References __setting, ip6_setting, ipv6_settings_scope, and SETTING_IP6.

◆ __setting() [2/3]

const struct setting len6_setting __setting ( SETTING_IP6 ,
len6  )

IPv6 prefix length setting.

References __setting, ipv6_settings_scope, len6_setting, and SETTING_IP6.

◆ __setting() [3/3]

const struct setting gateway6_setting __setting ( SETTING_IP6 ,
gateway6  )

Default gateway setting.

References __setting, gateway6_setting, ipv6_settings_scope, and SETTING_IP6.

◆ ipv6_applies()

int ipv6_applies ( struct settings *settings __unused,
const struct setting * setting )
static

Check applicability of IPv6 link-local address setting.

Parameters
settingsSettings block
settingSetting to fetch
Return values
appliesSetting applies within this settings block

Definition at line 1154 of file ipv6.c.

1155 {
1156
1157 return ( setting->scope == &ipv6_settings_scope );
1158}
const struct settings_scope ipv6_settings_scope
IPv6 settings scope.
Definition ipv6.c:1121
A setting.
Definition settings.h:24
const struct settings_scope * scope
Setting scope (or NULL)
Definition settings.h:50

References __unused, ipv6_settings_scope, and setting::scope.

◆ ipv6_fetch()

int ipv6_fetch ( struct settings * settings,
struct setting * setting,
void * data,
size_t len )
static

Fetch IPv6 link-local address setting.

Parameters
settingsSettings block
settingSetting to fetch
dataBuffer to fill with setting data
lenLength of buffer
Return values
lenLength of setting data, or negative error

Definition at line 1169 of file ipv6.c.

1170 {
1171 struct net_device *netdev =
1173 settings.settings );
1174 struct in6_addr ip6;
1175 uint8_t *len6;
1176 int prefix_len;
1177 int rc;
1178
1179 /* Construct link-local address from EUI-64 as per RFC 2464 */
1180 memset ( &ip6, 0, sizeof ( ip6 ) );
1181 prefix_len = ipv6_link_local ( &ip6, netdev );
1182 if ( prefix_len < 0 ) {
1183 rc = prefix_len;
1184 return rc;
1185 }
1186
1187 /* Handle setting */
1188 if ( setting_cmp ( setting, &ip6_setting ) == 0 ) {
1189
1190 /* Return link-local ip6 */
1191 if ( len > sizeof ( ip6 ) )
1192 len = sizeof ( ip6 );
1193 memcpy ( data, &ip6, len );
1194 return sizeof ( ip6 );
1195
1196 } else if ( setting_cmp ( setting, &len6_setting ) == 0 ) {
1197
1198 /* Return prefix length */
1199 if ( len ) {
1200 len6 = data;
1201 *len6 = prefix_len;
1202 }
1203 return sizeof ( *len6 );
1204
1205 }
1206
1207 return -ENOENT;
1208}
const struct setting len6_setting
const struct setting ip6_setting
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define ENOENT
No such file or directory.
Definition errno.h:515
static int ipv6_link_local(struct in6_addr *addr, struct net_device *netdev)
Construct link-local address via EUI-64.
Definition ipv6.h:236
int setting_cmp(const struct setting *a, const struct setting *b)
Compare two settings.
Definition settings.c:1121
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
A settings block.
Definition settings.h:133
struct settings * parent
Parent settings block.
Definition settings.h:139

References container_of, data, ENOENT, ip6_setting, ipv6_link_local(), len, len6_setting, memcpy(), memset(), netdev, settings::parent, rc, and setting_cmp().

◆ ipv6_register_settings()

int ipv6_register_settings ( struct net_device * netdev,
void * priv )
static

Register IPv6 link-local address settings.

Parameters
netdevNetwork device
privPrivate data
Return values
rcReturn status code

Definition at line 1223 of file ipv6.c.

1223 {
1224 struct settings *parent = netdev_settings ( netdev );
1225 struct settings *settings = priv;
1226 int rc;
1227
1228 /* Initialise and register settings */
1230 &netdev->refcnt, &ipv6_settings_scope );
1232 if ( ( rc = register_settings ( settings, parent,
1233 IPV6_SETTINGS_NAME ) ) != 0 )
1234 return rc;
1235
1236 return 0;
1237}
static void settings_init(struct settings *settings, struct settings_operations *op, struct refcnt *refcnt, const struct settings_scope *default_scope)
Initialise a settings block.
Definition settings.h:503
static struct settings_operations ipv6_settings_operations
IPv6 link-local address settings operations.
Definition ipv6.c:1211
#define IPV6_SETTINGS_NAME
IPv6 link-local address settings block name.
Definition ipv6.h:293
@ IPV6_ORDER_LINK_LOCAL
Link-local address.
Definition ipv6.h:285
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition netdevice.h:587
int register_settings(struct settings *settings, struct settings *parent, const char *name)
Register settings block.
Definition settings.c:476
int order
Sibling ordering.
Definition settings.h:149
static struct tlan_private * priv
Definition tlan.c:225

References IPV6_ORDER_LINK_LOCAL, IPV6_SETTINGS_NAME, ipv6_settings_operations, ipv6_settings_scope, netdev, netdev_settings(), settings::order, settings::parent, priv, rc, register_settings(), and settings_init().

◆ ipv6_create_routes()

int ipv6_create_routes ( struct net_device * netdev,
struct settings * settings )
static

Create IPv6 routing table based on configured settings.

Parameters
netdevNetwork device
settingsSettings block
Return values
rcReturn status code

Definition at line 1253 of file ipv6.c.

1254 {
1255 struct settings *child;
1256 struct settings *origin;
1257 struct in6_addr ip6_buf;
1258 struct in6_addr gateway6_buf;
1259 struct in6_addr *ip6 = &ip6_buf;
1260 struct in6_addr *gateway6 = &gateway6_buf;
1261 uint8_t len6;
1262 size_t len;
1263 int rc;
1264
1265 /* First, create routing table for any child settings. We do
1266 * this depth-first and in reverse order so that the end
1267 * result reflects the relative priorities of the settings
1268 * blocks.
1269 */
1270 list_for_each_entry_reverse ( child, &settings->children, siblings )
1271 ipv6_create_routes ( netdev, child );
1272
1273 /* Fetch IPv6 address, if any */
1275 ip6, sizeof ( *ip6 ) );
1276 if ( ( len != sizeof ( *ip6 ) ) || ( origin != settings ) )
1277 return 0;
1278
1279 /* Fetch prefix length, if defined */
1281 &len6, sizeof ( len6 ) );
1282 if ( ( len != sizeof ( len6 ) ) || ( origin != settings ) )
1283 len6 = 0;
1284 if ( len6 > IPV6_MAX_PREFIX_LEN )
1285 len6 = IPV6_MAX_PREFIX_LEN;
1286
1287 /* Fetch gateway, if defined */
1289 gateway6, sizeof ( *gateway6 ) );
1290 if ( ( len != sizeof ( *gateway6 ) ) || ( origin != settings ) )
1291 gateway6 = NULL;
1292
1293 /* Create or update route */
1294 if ( ( rc = ipv6_add_miniroute ( netdev, ip6, len6, gateway6 ) ) != 0){
1295 DBGC ( netdev, "IPv6 %s could not add route: %s\n",
1296 netdev->name, strerror ( rc ) );
1297 return rc;
1298 }
1299
1300 return 0;
1301}
const struct setting gateway6_setting
uint64_t origin
Origin.
Definition hyperv.h:9
static int ipv6_create_routes(struct net_device *netdev, struct settings *settings)
Create IPv6 routing table based on configured settings.
Definition ipv6.c:1253
int ipv6_add_miniroute(struct net_device *netdev, struct in6_addr *address, unsigned int prefix_len, struct in6_addr *router)
Add IPv6 routing table entry.
Definition ipv6.c:218
#define list_for_each_entry_reverse(pos, head, member)
Iterate over entries in a list in reverse order.
Definition list.h:445
int fetch_setting(struct settings *settings, const struct setting *setting, struct settings **origin, struct setting *fetched, void *data, size_t len)
Fetch setting.
Definition settings.c:667
struct list_head children
Child settings blocks.
Definition settings.h:143

References settings::children, DBGC, fetch_setting(), gateway6_setting, ip6_setting, ipv6_add_miniroute(), ipv6_create_routes(), IPV6_MAX_PREFIX_LEN, len, len6_setting, list_for_each_entry_reverse, netdev, NULL, origin, rc, and strerror().

Referenced by ipv6_create_all_routes(), and ipv6_create_routes().

◆ ipv6_create_all_routes()

int ipv6_create_all_routes ( void )
static

Create IPv6 routing table based on configured settings.

Return values
rcReturn status code

Definition at line 1308 of file ipv6.c.

1308 {
1309 struct ipv6_miniroute *miniroute;
1310 struct ipv6_miniroute *tmp;
1311 struct net_device *netdev;
1312 struct settings *settings;
1313 int rc;
1314
1315 /* Delete all existing routes */
1316 list_for_each_entry_safe ( miniroute, tmp, &ipv6_miniroutes, list )
1317 ipv6_del_miniroute ( miniroute );
1318
1319 /* Create routes for each configured network device */
1322 if ( ( rc = ipv6_create_routes ( netdev, settings ) ) != 0 )
1323 return rc;
1324 }
1325
1326 return 0;
1327}
void ipv6_del_miniroute(struct ipv6_miniroute *miniroute)
Delete IPv6 minirouting table entry.
Definition ipv6.c:293
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define for_each_netdev(netdev)
Iterate over all network devices.
Definition netdevice.h:547

References for_each_netdev, ipv6_create_routes(), ipv6_del_miniroute(), ipv6_miniroutes, list_for_each_entry_safe, netdev, netdev_settings(), rc, and tmp.

◆ REQUIRING_SYMBOL()

REQUIRING_SYMBOL ( ipv6_protocol )

◆ REQUIRE_OBJECT() [1/2]

REQUIRE_OBJECT ( icmpv6 )

◆ REQUIRE_OBJECT() [2/2]

REQUIRE_OBJECT ( ndp )

Variable Documentation

◆ ipv6_miniroutes

struct list_head ipv6_miniroutes = LIST_HEAD_INIT ( ipv6_miniroutes )

◆ ipv6_stats

struct ip_statistics ipv6_stats
static

IPv6 statistics.

Definition at line 64 of file ipv6.c.

Referenced by __ip_statistics_family(), ipv6_rx(), and ipv6_tx().

◆ ipv6_reassembler

struct fragment_reassembler ipv6_reassembler
static
Initial value:
= {
.list = LIST_HEAD_INIT ( ipv6_reassembler.list ),
.is_fragment = ipv6_is_fragment,
.fragment_offset = ipv6_fragment_offset,
.more_fragments = ipv6_more_fragments,
.stats = &ipv6_stats,
}
static size_t ipv6_fragment_offset(struct io_buffer *iobuf, size_t hdrlen)
Get fragment offset.
Definition ipv6.c:458
static int ipv6_more_fragments(struct io_buffer *iobuf, size_t hdrlen)
Check if more fragments exist.
Definition ipv6.c:472
static int ipv6_is_fragment(struct fragment *fragment, struct io_buffer *iobuf, size_t hdrlen)
Check if fragment matches fragment reassembly buffer.
Definition ipv6.c:436
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition list.h:31

Fragment reassembler.

Definition at line 480 of file ipv6.c.

480 {
481 .list = LIST_HEAD_INIT ( ipv6_reassembler.list ),
482 .is_fragment = ipv6_is_fragment,
483 .fragment_offset = ipv6_fragment_offset,
484 .more_fragments = ipv6_more_fragments,
485 .stats = &ipv6_stats,
486};

Referenced by ipv6_rx().

◆ __net_protocol

struct net_protocol ipv6_protocol __net_protocol
Initial value:
= {
.name = "IPv6",
.net_proto = htons ( ETH_P_IPV6 ),
.net_addr_len = sizeof ( struct in6_addr ),
.rx = ipv6_rx,
.ntoa = ipv6_ntoa,
}
#define ETH_P_IPV6
Definition if_ether.h:23
static const char * ipv6_ntoa(const void *net_addr)
Transcribe IPv6 address.
Definition ipv6.c:941
static int ipv6_rx(struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest __unused, const void *ll_source __unused, unsigned int flags __unused)
Process incoming IPv6 packets.
Definition ipv6.c:650
u8 rx[WPA_TKIP_MIC_KEY_LEN]
MIC key for packets from the AP.
Definition wpa.h:1

IPv6 protocol.

AoE protocol.

Definition at line 1049 of file ipv6.c.

1049 {
1050 .name = "IPv6",
1051 .net_proto = htons ( ETH_P_IPV6 ),
1052 .net_addr_len = sizeof ( struct in6_addr ),
1053 .rx = ipv6_rx,
1054 .ntoa = ipv6_ntoa,
1055};

◆ __tcpip_net_protocol

struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol
Initial value:
= {
.name = "IPv6",
.sa_family = AF_INET6,
.header_len = sizeof ( struct ipv6_header ),
.net_protocol = &ipv6_protocol,
.tx = ipv6_tx,
.netdev = ipv6_netdev,
}
static int ipv6_tx(struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, struct net_device *netdev, uint16_t *trans_csum)
Transmit IPv6 packet.
Definition ipv6.c:526
static struct net_device * ipv6_netdev(struct sockaddr_tcpip *st_dest)
Determine transmitting network device.
Definition ipv6.c:384
A network-layer protocol.
Definition netdevice.h:65

IPv6 TCPIP net protocol.

Definition at line 1058 of file ipv6.c.

1058 {
1059 .name = "IPv6",
1060 .sa_family = AF_INET6,
1061 .header_len = sizeof ( struct ipv6_header ),
1062 .net_protocol = &ipv6_protocol,
1063 .tx = ipv6_tx,
1064 .netdev = ipv6_netdev,
1065};

◆ __sockaddr_converter

struct sockaddr_converter ipv6_sockaddr_converter __sockaddr_converter
Initial value:
= {
.family = AF_INET6,
.ntoa = ipv6_sock_ntoa,
.aton = ipv6_sock_aton,
}
static const char * ipv6_sock_ntoa(struct sockaddr *sa)
Transcribe IPv6 socket address.
Definition ipv6.c:951
static int ipv6_sock_aton(const char *string, struct sockaddr *sa)
Parse IPv6 socket address.
Definition ipv6.c:981

IPv6 socket address converter.

Definition at line 1068 of file ipv6.c.

1068 {
1069 .family = AF_INET6,
1070 .ntoa = ipv6_sock_ntoa,
1071 .aton = ipv6_sock_aton,
1072};

◆ ipv6_settings_scope

const struct settings_scope ipv6_settings_scope

IPv6 settings scope.

IPv6 setting scope.

Definition at line 1121 of file ipv6.c.

Referenced by __setting(), __setting(), __setting(), dhcpv6_applies(), ipv6_applies(), ipv6_register_settings(), and ndp_prefix_applies().

◆ ipv6_settings_operations

struct settings_operations ipv6_settings_operations
static
Initial value:
= {
.applies = ipv6_applies,
.fetch = ipv6_fetch,
}
static int ipv6_applies(struct settings *settings __unused, const struct setting *setting)
Check applicability of IPv6 link-local address setting.
Definition ipv6.c:1154
static int ipv6_fetch(struct settings *settings, struct setting *setting, void *data, size_t len)
Fetch IPv6 link-local address setting.
Definition ipv6.c:1169

IPv6 link-local address settings operations.

Definition at line 1211 of file ipv6.c.

1211 {
1212 .applies = ipv6_applies,
1213 .fetch = ipv6_fetch,
1214};

Referenced by ipv6_register_settings().

◆ __net_driver

struct net_driver ipv6_driver __net_driver
Initial value:
= {
.name = "IPv6",
.priv_len = sizeof ( struct settings ),
}
static int ipv6_register_settings(struct net_device *netdev, void *priv)
Register IPv6 link-local address settings.
Definition ipv6.c:1223

IPv6 network device driver.

Definition at line 1240 of file ipv6.c.

1240 {
1241 .name = "IPv6",
1242 .priv_len = sizeof ( struct settings ),
1243 .probe = ipv6_register_settings,
1244};

◆ __settings_applicator

struct settings_applicator ipv6_settings_applicator __settings_applicator
Initial value:
= {
}
static int ipv6_create_all_routes(void)
Create IPv6 routing table based on configured settings.
Definition ipv6.c:1308

IPv6 settings applicator.

Definition at line 1330 of file ipv6.c.

1330 {
1331 .apply = ipv6_create_all_routes,
1332};