aboutsummaryrefslogtreecommitdiffstats
path: root/lib/icmpv6.h
blob: 44b9b7316c9c53cbfd38b8ccce0dd789d3d6d4d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#pragma once

#include <stdbool.h>

#include <osmocom/core/msgb.h>
#include <osmocom/core/endian.h>

#include "../gtp/gtp.h"
#include "../gtp/pdp.h"

#define ICMPv6_OPT_TYPE_PREFIX_INFO 0x03

#define foreach_icmpv6_opt(icmpv6_pkt, icmpv6_len, opt_hdr) \
		for (opt_hdr = (struct icmpv6_opt_hdr *)(icmpv6_pkt)->options; \
		     (uint8_t*)(opt_hdr) + sizeof(struct icmpv6_opt_hdr) <= (((uint8_t*)(icmpv6_pkt)) + (icmpv6_len)); \
		     opt_hdr = (struct icmpv6_opt_hdr*)((uint8_t*)(opt_hdr) + (opt_hdr)->len) \
		    )

struct icmpv6_hdr {
	uint8_t type;
	uint8_t code;
	uint16_t csum;
} __attribute__ ((packed));

/* RFC4861 Section 4.1 */
struct icmpv6_rsol_hdr {
	struct icmpv6_hdr hdr;
	uint32_t reserved;
	uint8_t options[0];
} __attribute__ ((packed));

/* RFC4861 Section 4.2 */
struct icmpv6_radv_hdr {
	struct icmpv6_hdr hdr;
	uint8_t cur_ho_limit;
#if OSMO_IS_LITTLE_ENDIAN
	uint8_t res:6,
		m:1,
		o:1;
#else
	uint8_t m:1,
		o:1,
		res:6;
#endif
	uint16_t router_lifetime;
	uint32_t reachable_time;
	uint32_t retrans_timer;
	uint8_t options[0];
} __attribute__ ((packed));


/* RFC4861 Section 4.6 */
struct icmpv6_opt_hdr {
	uint8_t type;
	/* length in units of 8 octets, including type+len! */
	uint8_t len;
	uint8_t data[0];
} __attribute__ ((packed));

/* RFC4861 Section 4.6.2 */
struct icmpv6_opt_prefix {
	struct icmpv6_opt_hdr hdr;
	uint8_t prefix_len;
#if OSMO_IS_LITTLE_ENDIAN
	uint8_t res:6,
		a:1,
		l:1;
#else
	uint8_t l:1,
		a:1,
		res:6;
#endif
	uint32_t valid_lifetime;
	uint32_t preferred_lifetime;
	uint32_t res2;
	uint8_t prefix[16];
} __attribute__ ((packed));

struct msgb *icmpv6_construct_rs(const struct in6_addr *saddr);

int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp,
			const struct in6_addr *pdp_prefix,
			const struct in6_addr *own_ll_addr,
			const uint8_t *pack, unsigned len);

struct icmpv6_radv_hdr *icmpv6_validate_router_adv(const uint8_t *pack, unsigned len);


/* RFC3307 link-local scope multicast address */
extern const struct in6_addr all_router_mcast_addr;