2 * BIRD -- RAdv Packet Processing
5 * Can be freely distributed and used under the terms of the GNU GPL.
24 #define OPT_RA_MANAGED 0x80
25 #define OPT_RA_OTHER_CFG 0x40
32 struct radv_opt_prefix
39 u32 preferred_lifetime
;
44 #define OPT_PX_ONLINK 0x80
45 #define OPT_PX_AUTONOMOUS 0x40
74 static struct radv_prefix_config default_prefix
= {
77 .valid_lifetime
= DEFAULT_VALID_LIFETIME
,
78 .preferred_lifetime
= DEFAULT_PREFERRED_LIFETIME
82 static struct radv_prefix_config
*
83 radv_prefix_match(struct radv_iface
*ifa
, struct ifa
*a
)
85 struct proto
*p
= &ifa
->ra
->p
;
86 struct radv_config
*cf
= (struct radv_config
*) (p
->cf
);
87 struct radv_prefix_config
*pc
;
89 if (a
->scope
<= SCOPE_LINK
)
92 WALK_LIST(pc
, ifa
->cf
->pref_list
)
93 if ((a
->pxlen
>= pc
->pxlen
) && ipa_in_net(a
->prefix
, pc
->prefix
, pc
->pxlen
))
96 WALK_LIST(pc
, cf
->pref_list
)
97 if ((a
->pxlen
>= pc
->pxlen
) && ipa_in_net(a
->prefix
, pc
->prefix
, pc
->pxlen
))
100 return &default_prefix
;
104 radv_prepare_rdnss(struct radv_iface
*ifa
, list
*rdnss_list
, char **buf
, char *bufend
)
106 struct radv_rdnss_config
*rcf
= HEAD(*rdnss_list
);
108 while(NODE_VALID(rcf
))
110 struct radv_rdnss_config
*rcf_base
= rcf
;
111 struct radv_opt_rdnss
*op
= (void *) *buf
;
112 int max_i
= (bufend
- *buf
- sizeof(struct radv_opt_rdnss
)) / sizeof(ip_addr
);
118 op
->type
= OPT_RDNSS
;
121 if (rcf
->lifetime_mult
)
122 op
->lifetime
= htonl(rcf
->lifetime_mult
* ifa
->cf
->max_ra_int
);
124 op
->lifetime
= htonl(rcf
->lifetime
);
126 while(NODE_VALID(rcf
) &&
127 (rcf
->lifetime
== rcf_base
->lifetime
) &&
128 (rcf
->lifetime_mult
== rcf_base
->lifetime_mult
))
133 op
->servers
[i
] = rcf
->server
;
134 ipa_hton(op
->servers
[i
]);
137 rcf
= NODE_NEXT(rcf
);
141 *buf
+= 8 * op
->length
;
147 log(L_WARN
"%s: Too many RA options on interface %s",
148 ifa
->ra
->p
.name
, ifa
->iface
->name
);
153 radv_process_domain(struct radv_dnssl_config
*cf
)
155 /* Format of domain in search list is <size> <label> <size> <label> ... 0 */
157 char *dom
= cf
->domain
;
158 char *dom_end
= dom
; /* Just to */
159 u8
*dlen_save
= &cf
->dlen_first
;
164 dom_end
= strchr(dom
, '.');
165 len
= dom_end
? (uint
)(dom_end
- dom
) : strlen(dom
);
167 if (len
< 1 || len
> 63)
171 dlen_save
= (u8
*) dom_end
;
176 len
= dom
- cf
->domain
;
186 radv_prepare_dnssl(struct radv_iface
*ifa
, list
*dnssl_list
, char **buf
, char *bufend
)
188 struct radv_dnssl_config
*dcf
= HEAD(*dnssl_list
);
190 while(NODE_VALID(dcf
))
192 struct radv_dnssl_config
*dcf_base
= dcf
;
193 struct radv_opt_dnssl
*op
= (void *) *buf
;
194 int bsize
= bufend
- *buf
- sizeof(struct radv_opt_dnssl
);
200 bsize
= bsize
& ~7; /* Round down to multiples of 8 */
202 op
->type
= OPT_DNSSL
;
205 if (dcf
->lifetime_mult
)
206 op
->lifetime
= htonl(dcf
->lifetime_mult
* ifa
->cf
->max_ra_int
);
208 op
->lifetime
= htonl(dcf
->lifetime
);
210 while(NODE_VALID(dcf
) &&
211 (dcf
->lifetime
== dcf_base
->lifetime
) &&
212 (dcf
->lifetime_mult
== dcf_base
->lifetime_mult
))
214 if (bpos
+ dcf
->dlen_all
+ 1 > bsize
)
217 op
->domain
[bpos
++] = dcf
->dlen_first
;
218 memcpy(op
->domain
+ bpos
, dcf
->domain
, dcf
->dlen_all
);
219 bpos
+= dcf
->dlen_all
;
221 dcf
= NODE_NEXT(dcf
);
224 int blen
= (bpos
+ 7) / 8;
225 bzero(op
->domain
+ bpos
, 8 * blen
- bpos
);
226 op
->length
= 1 + blen
;
227 *buf
+= 8 * op
->length
;
233 log(L_WARN
"%s: Too many RA options on interface %s",
234 ifa
->ra
->p
.name
, ifa
->iface
->name
);
239 radv_prepare_ra(struct radv_iface
*ifa
)
241 struct proto_radv
*ra
= ifa
->ra
;
242 struct radv_config
*cf
= (struct radv_config
*) (ra
->p
.cf
);
243 struct radv_iface_config
*ic
= ifa
->cf
;
245 char *buf
= ifa
->sk
->tbuf
;
246 char *bufstart
= buf
;
247 char *bufend
= buf
+ ifa
->sk
->tbsize
;
249 struct radv_ra_packet
*pkt
= (void *) buf
;
250 pkt
->type
= ICMPV6_RA
;
253 pkt
->current_hop_limit
= ic
->current_hop_limit
;
254 pkt
->router_lifetime
= (ra
->active
|| !ic
->default_lifetime_sensitive
) ?
255 htons(ic
->default_lifetime
) : 0;
256 pkt
->flags
= (ic
->managed
? OPT_RA_MANAGED
: 0) |
257 (ic
->other_config
? OPT_RA_OTHER_CFG
: 0) |
258 (pkt
->router_lifetime
? ic
->default_preference
: 0);
259 pkt
->reachable_time
= htonl(ic
->reachable_time
);
260 pkt
->retrans_timer
= htonl(ic
->retrans_timer
);
265 struct radv_opt_mtu
*om
= (void *) buf
;
269 om
->mtu
= htonl(ic
->link_mtu
);
274 WALK_LIST(addr
, ifa
->iface
->addrs
)
276 struct radv_prefix_config
*pc
;
277 pc
= radv_prefix_match(ifa
, addr
);
282 if (buf
+ sizeof(struct radv_opt_prefix
) > bufend
)
284 log(L_WARN
"%s: Too many prefixes on interface %s", ra
->p
.name
, ifa
->iface
->name
);
288 struct radv_opt_prefix
*op
= (void *) buf
;
289 op
->type
= OPT_PREFIX
;
291 op
->pxlen
= addr
->pxlen
;
292 op
->flags
= (pc
->onlink
? OPT_PX_ONLINK
: 0) |
293 (pc
->autonomous
? OPT_PX_AUTONOMOUS
: 0);
294 op
->valid_lifetime
= (ra
->active
|| !pc
->valid_lifetime_sensitive
) ?
295 htonl(pc
->valid_lifetime
) : 0;
296 op
->preferred_lifetime
= (ra
->active
|| !pc
->preferred_lifetime_sensitive
) ?
297 htonl(pc
->preferred_lifetime
) : 0;
299 op
->prefix
= addr
->prefix
;
300 ipa_hton(op
->prefix
);
304 if (! ic
->rdnss_local
)
305 if (radv_prepare_rdnss(ifa
, &cf
->rdnss_list
, &buf
, bufend
) < 0)
308 if (radv_prepare_rdnss(ifa
, &ic
->rdnss_list
, &buf
, bufend
) < 0)
311 if (! ic
->dnssl_local
)
312 if (radv_prepare_dnssl(ifa
, &cf
->dnssl_list
, &buf
, bufend
) < 0)
315 if (radv_prepare_dnssl(ifa
, &ic
->dnssl_list
, &buf
, bufend
) < 0)
319 ifa
->plen
= buf
- bufstart
;
324 radv_send_ra(struct radv_iface
*ifa
, int shutdown
)
326 struct proto_radv
*ra
= ifa
->ra
;
328 /* We store prepared RA in tbuf */
330 radv_prepare_ra(ifa
);
335 * Modify router lifetime to 0, it is not restored because we suppose that
336 * the iface will be removed. The preference value also has to be zeroed.
337 * (RFC 4191 2.2: If router lifetime is 0, the preference value must be 0.)
340 struct radv_ra_packet
*pkt
= (void *) ifa
->sk
->tbuf
;
341 pkt
->router_lifetime
= 0;
342 pkt
->flags
&= ~RA_PREF_MASK
;
345 RADV_TRACE(D_PACKETS
, "Sending RA via %s", ifa
->iface
->name
);
346 sk_send_to(ifa
->sk
, ifa
->plen
, IP6_ALL_NODES
, 0);
351 radv_rx_hook(sock
*sk
, uint size
)
353 struct radv_iface
*ifa
= sk
->data
;
354 struct proto_radv
*ra
= ifa
->ra
;
356 /* We want just packets from sk->iface */
357 if (sk
->lifindex
!= sk
->iface
->index
)
360 if (ipa_equal(sk
->faddr
, ifa
->addr
->ip
))
366 byte
*buf
= sk
->rbuf
;
371 /* Validation is a bit sloppy - Hop Limit is not checked and
372 length of options is ignored for RS and left to later for RA */
377 RADV_TRACE(D_PACKETS
, "Received RS from %I via %s",
378 sk
->faddr
, ifa
->iface
->name
);
379 radv_iface_notify(ifa
, RA_EV_RS
);
383 RADV_TRACE(D_PACKETS
, "Received RA from %I via %s",
384 sk
->faddr
, ifa
->iface
->name
);
385 /* FIXME - there should be some checking of received RAs, but we just ignore them */
394 radv_tx_hook(sock
*sk
)
396 struct radv_iface
*ifa
= sk
->data
;
397 log(L_WARN
"%s: TX hook called", ifa
->ra
->p
.name
);
401 radv_err_hook(sock
*sk
, int err
)
403 struct radv_iface
*ifa
= sk
->data
;
404 log(L_ERR
"%s: Socket error on %s: %M", ifa
->ra
->p
.name
, ifa
->iface
->name
, err
);
408 radv_sk_open(struct radv_iface
*ifa
)
410 sock
*sk
= sk_new(ifa
->ra
->p
.pool
);
412 sk
->dport
= ICMPV6_PROTO
;
413 sk
->saddr
= ifa
->addr
->ip
;
415 sk
->ttl
= 255; /* Mandatory for Neighbor Discovery packets */
416 sk
->rx_hook
= radv_rx_hook
;
417 sk
->tx_hook
= radv_tx_hook
;
418 sk
->err_hook
= radv_err_hook
;
419 sk
->iface
= ifa
->iface
;
420 sk
->rbsize
= 1024; // bufsize(ifa);
421 sk
->tbsize
= 1024; // bufsize(ifa);
423 sk
->flags
= SKF_LADDR_RX
;
428 /* We want listen just to ICMPv6 messages of type RS and RA */
429 if (sk_set_icmp6_filter(sk
, ICMPV6_RS
, ICMPV6_RA
) < 0)
432 if (sk_setup_multicast(sk
) < 0)
435 if (sk_join_group(sk
, IP6_ALL_ROUTERS
) < 0)
442 sk_log_error(sk
, ifa
->ra
->p
.name
);