summaryrefslogtreecommitdiff
path: root/proto/radv/radv.h
blob: ba4a1b6c75eb680e393dbb8eca0505c9998529a0 (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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*
 *	BIRD -- Router Advertisement
 *
 *	(c) 2011--2019 Ondrej Zajicek <santiago@crfreenet.org>
 *	(c) 2011--2019 CZ.NIC z.s.p.o.
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#ifndef _BIRD_RADV_H_
#define _BIRD_RADV_H_

#include "nest/bird.h"

#include "lib/ip.h"
#include "lib/lists.h"
#include "lib/socket.h"
#include "lib/timer.h"
#include "lib/resource.h"
#include "nest/protocol.h"
#include "nest/iface.h"
#include "nest/route.h"
#include "nest/cli.h"
#include "nest/locks.h"
#include "conf/conf.h"
#include "lib/string.h"


#define ICMPV6_PROTO 58

#define ICMPV6_RS 133
#define ICMPV6_RA 134

#define MAX_INITIAL_RTR_ADVERTISEMENTS 3
#define MAX_INITIAL_RTR_ADVERT_INTERVAL (16 S_)

#define DEFAULT_MAX_RA_INT 600
#define DEFAULT_MIN_DELAY 3
#define DEFAULT_CURRENT_HOP_LIMIT 64

#define DEFAULT_VALID_LIFETIME 86400
#define DEFAULT_PREFERRED_LIFETIME 14400

#define DEFAULT_DNS_LIFETIME_MULT 3


struct radv_config
{
  struct proto_config c;
  list patt_list;		/* List of iface configs (struct radv_iface_config) */
  list pref_list;		/* Global list of prefix configs (struct radv_prefix_config) */
  list rdnss_list;		/* Global list of RDNSS configs (struct radv_rdnss_config) */
  list dnssl_list;		/* Global list of DNSSL configs (struct radv_dnssl_config) */
  list custom_list;		/* Global list of custom configs (struct radv_custom_config) */

  net_addr trigger;		/* Prefix of a trigger route, if defined */
  u8 propagate_routes;		/* Do we propagate more specific routes (RFC 4191)? */
  u32 max_linger_time;		/* Maximum of interface route_linger_time */
};

struct radv_iface_config
{
  struct iface_patt i;
  list pref_list;		/* Local list of prefix configs (struct radv_prefix_config) */
  list rdnss_list;		/* Local list of RDNSS configs (struct radv_rdnss_config) */
  list dnssl_list;		/* Local list of DNSSL configs (struct radv_dnssl_config) */
  list custom_list;		/* Local list of custom configs (struct radv_custom_config) */

  u32 min_ra_int;		/* Standard options from RFC 4861 */
  u32 max_ra_int;
  u32 min_delay;

  u8 solicited_ra_unicast;	/* Send solicited RAs as unicast */

  u32 prefix_linger_time;	/* How long we advertise dead prefixes with lifetime 0 */
  u32 route_linger_time;	/* How long we advertise dead routes with lifetime 0 */

  u8 rdnss_local;		/* Global list is not used for RDNSS */
  u8 dnssl_local;		/* Global list is not used for DNSSL */
  u8 custom_local;		/* Global list is not used for custom */

  u8 managed;			/* Standard options from RFC 4861 */
  u8 other_config;
  u32 link_mtu;
  u32 reachable_time;
  u32 retrans_timer;
  u32 current_hop_limit;
  u32 default_lifetime;
  u32 route_lifetime;		/* Lifetime for the RFC 4191 routes */
  u8 default_lifetime_sensitive; /* Whether default_lifetime depends on trigger */
  u8 route_lifetime_sensitive;	/* Whether route_lifetime depends on trigger */
  u8 default_preference;	/* Default Router Preference (RFC 4191) */
  u8 route_preference;		/* Specific Route Preference (RFC 4191) */
};

struct radv_prefix_config
{
  node n;
  net_addr_ip6 prefix;

  u8 skip;			/* Do not include this prefix to RA */
  u8 onlink;			/* Standard options from RFC 4861 */
  u8 autonomous;
  u32 valid_lifetime;
  u32 preferred_lifetime;
  u8 valid_lifetime_sensitive;	 /* Whether valid_lifetime depends on trigger */
  u8 preferred_lifetime_sensitive; /* Whether preferred_lifetime depends on trigger */
};

struct radv_rdnss_config
{
  node n;
  u32 lifetime;			/* Valid if lifetime_mult is 0 */
  u16 lifetime_mult;		/* Lifetime specified as multiple of max_ra_int */
  ip6_addr server;		/* IP address of recursive DNS server */
};

struct radv_dnssl_config
{
  node n;
  u32 lifetime;			/* Valid if lifetime_mult is 0 */
  u16 lifetime_mult;		/* Lifetime specified as multiple of max_ra_int */
  u8 dlen_first;		/* Length of first label in domain */
  u8 dlen_all;			/* Both dlen_ filled in radv_process_domain() */
  const char *domain;		/* Domain for DNS search list, in processed form */
};

struct radv_custom_config
{
  node n;
  u8 type;			/* Identifier of the type of option */
  const struct adata *payload;	/* Payload of the option */
};

/*
 * One more specific route as per RFC 4191.
 *
 * Note that it does *not* contain the next hop field. The next hop is always
 * the router sending the advertisment and the more specific route only allows
 * overriding the preference of the route.
 */
struct radv_route
{
  u32 lifetime;			/* Lifetime from an attribute */
  u8 lifetime_set;		/* Whether lifetime is defined */
  u8 preference;		/* Preference of the route, RA_PREF_* */
  u8 preference_set;		/* Whether preference is defined */
  u8 valid;			/* Whethe route is valid or withdrawn */
  btime changed;		/* Last time when the route changed */

  struct fib_node n;
};

struct radv_proto
{
  struct proto p;
  list iface_list;		/* List of active ifaces */
  u8 valid;			/* Router is valid for forwarding, used for shutdown */
  u8 active;			/* Whether radv is active w.r.t. triggers */
  u8 fib_up;			/* FIB table (routes) is initialized */
  struct fib routes;		/* FIB table of specific routes (struct radv_route) */
  btime prune_time;		/* Next time of route table pruning */
};

struct radv_prefix		/* One prefix we advertise */
{
  node n;
  net_addr_ip6 prefix;

  u8 valid;			/* Is the prefix valid? If not, we advertise it
				   with 0 lifetime, so clients stop using it */
  u8 mark;			/* A temporary mark for processing */
  btime changed;		/* Last time when the prefix changed */
  struct radv_prefix_config *cf; /* The config tied to this prefix */
};

struct radv_iface
{
  node n;
  struct radv_proto *ra;
  struct radv_iface_config *cf;	/* Related config, must be updated in reconfigure */
  struct iface *iface;
  struct ifa *addr;		/* Link-local address of iface */
  struct pool *pool;		/* A pool for interface-specific things */
  list prefixes;		/* The prefixes we advertise (struct radv_prefix) */
  btime prune_time;		/* Next time of prefix list pruning */
  btime valid_time;		/* Cached packet is valid until first linger timeout */

  timer *timer;
  struct object_lock *lock;
  sock *sk;

  btime last;			/* Time of last sending of RA */
  u16 plen;			/* Length of prepared RA in tbuf, or 0 if not valid */
  byte initial;			/* How many RAs are still to be sent as initial */
};

#define RA_EV_INIT 1		/* Switch to initial mode */
#define RA_EV_CHANGE 2		/* Change of options or prefixes */
#define RA_EV_RS 3		/* Received RS */

/* Default Router Preferences (RFC 4191) */
#define RA_PREF_LOW	0x18
#define RA_PREF_MEDIUM	0x00
#define RA_PREF_HIGH	0x08
#define RA_PREF_MASK	0x18

/* Attributes */
#define EA_RA_PREFERENCE	EA_CODE(PROTOCOL_RADV, 0)
#define EA_RA_LIFETIME		EA_CODE(PROTOCOL_RADV, 1)

#ifdef LOCAL_DEBUG
#define RADV_FORCE_DEBUG 1
#else
#define RADV_FORCE_DEBUG 0
#endif
#define RADV_TRACE(flags, msg, args...) do { if ((p->p.debug & flags) || RADV_FORCE_DEBUG) \
	log(L_TRACE "%s: " msg, p->p.name , ## args ); } while(0)


/* Invalidate cached RA packet */
static inline void radv_invalidate(struct radv_iface *ifa)
{ ifa->plen = 0; }

/* radv.c */
void radv_iface_notify(struct radv_iface *ifa, int event);

/* packets.c */
int radv_process_domain(struct radv_dnssl_config *cf);
void radv_send_ra(struct radv_iface *ifa, ip_addr to);
int radv_sk_open(struct radv_iface *ifa);



#endif /* _BIRD_RADV_H_ */