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
? (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
->flags
= (ic
->managed
? OPT_RA_MANAGED
: 0) |
255 (ic
->other_config
? OPT_RA_OTHER_CFG
: 0);
256 pkt
->router_lifetime
= (ra
->active
|| !ic
->default_lifetime_sensitive
) ?
257 htons(ic
->default_lifetime
) : 0;
258 pkt
->reachable_time
= htonl(ic
->reachable_time
);
259 pkt
->retrans_timer
= htonl(ic
->retrans_timer
);
264 struct radv_opt_mtu
*om
= (void *) buf
;
268 om
->mtu
= htonl(ic
->link_mtu
);
273 WALK_LIST(addr
, ifa
->iface
->addrs
)
275 struct radv_prefix_config
*pc
;
276 pc
= radv_prefix_match(ifa
, addr
);
281 if (buf
+ sizeof(struct radv_opt_prefix
) > bufend
)
283 log(L_WARN
"%s: Too many prefixes on interface %s", ra
->p
.name
, ifa
->iface
->name
);
287 struct radv_opt_prefix
*op
= (void *) buf
;
288 op
->type
= OPT_PREFIX
;
290 op
->pxlen
= addr
->pxlen
;
291 op
->flags
= (pc
->onlink
? OPT_PX_ONLINK
: 0) |
292 (pc
->autonomous
? OPT_PX_AUTONOMOUS
: 0);
293 op
->valid_lifetime
= (ra
->active
|| !pc
->valid_lifetime_sensitive
) ?
294 htonl(pc
->valid_lifetime
) : 0;
295 op
->preferred_lifetime
= (ra
->active
|| !pc
->preferred_lifetime_sensitive
) ?
296 htonl(pc
->preferred_lifetime
) : 0;
298 op
->prefix
= addr
->prefix
;
299 ipa_hton(op
->prefix
);
303 if (! ic
->rdnss_local
)
304 if (radv_prepare_rdnss(ifa
, &cf
->rdnss_list
, &buf
, bufend
) < 0)
307 if (radv_prepare_rdnss(ifa
, &ic
->rdnss_list
, &buf
, bufend
) < 0)
310 if (! ic
->dnssl_local
)
311 if (radv_prepare_dnssl(ifa
, &cf
->dnssl_list
, &buf
, bufend
) < 0)
314 if (radv_prepare_dnssl(ifa
, &ic
->dnssl_list
, &buf
, bufend
) < 0)
318 ifa
->plen
= buf
- bufstart
;
323 radv_send_ra(struct radv_iface
*ifa
, int shutdown
)
325 struct proto_radv
*ra
= ifa
->ra
;
327 /* We store prepared RA in tbuf */
329 radv_prepare_ra(ifa
);
333 /* Modify router lifetime to 0, it is not restored because
334 we suppose that the iface will be removed */
335 struct radv_ra_packet
*pkt
= (void *) ifa
->sk
->tbuf
;
336 pkt
->router_lifetime
= 0;
339 RADV_TRACE(D_PACKETS
, "Sending RA via %s", ifa
->iface
->name
);
340 sk_send_to(ifa
->sk
, ifa
->plen
, AllNodes
, 0);
345 radv_rx_hook(sock
*sk
, int size
)
347 struct radv_iface
*ifa
= sk
->data
;
348 struct proto_radv
*ra
= ifa
->ra
;
350 /* We want just packets from sk->iface */
351 if (sk
->lifindex
!= sk
->iface
->index
)
354 if (ipa_equal(sk
->faddr
, ifa
->addr
->ip
))
360 byte
*buf
= sk
->rbuf
;
365 /* Validation is a bit sloppy - Hop Limit is not checked and
366 length of options is ignored for RS and left to later for RA */
371 RADV_TRACE(D_PACKETS
, "Received RS from %I via %s",
372 sk
->faddr
, ifa
->iface
->name
);
373 radv_iface_notify(ifa
, RA_EV_RS
);
377 RADV_TRACE(D_PACKETS
, "Received RA from %I via %s",
378 sk
->faddr
, ifa
->iface
->name
);
379 /* FIXME - there should be some checking of received RAs, but we just ignore them */
388 radv_tx_hook(sock
*sk
)
390 struct radv_iface
*ifa
= sk
->data
;
391 log(L_WARN
"%s: TX hook called", ifa
->ra
->p
.name
);
395 radv_err_hook(sock
*sk
, int err
)
397 struct radv_iface
*ifa
= sk
->data
;
398 log(L_ERR
"%s: Socket error on %s: %M", ifa
->ra
->p
.name
, ifa
->iface
->name
, err
);
402 radv_sk_open(struct radv_iface
*ifa
)
404 sock
*sk
= sk_new(ifa
->ra
->p
.pool
);
406 sk
->dport
= ICMPV6_PROTO
;
407 sk
->saddr
= ifa
->addr
->ip
;
409 sk
->ttl
= 255; /* Mandatory for Neighbor Discovery packets */
410 sk
->rx_hook
= radv_rx_hook
;
411 sk
->tx_hook
= radv_tx_hook
;
412 sk
->err_hook
= radv_err_hook
;
413 sk
->iface
= ifa
->iface
;
414 sk
->rbsize
= 1024; // bufsize(ifa);
415 sk
->tbsize
= 1024; // bufsize(ifa);
417 sk
->flags
= SKF_LADDR_RX
;
419 if (sk_open(sk
) != 0)
422 /* We want listen just to ICMPv6 messages of type RS and RA */
423 if (sk_set_icmp_filter(sk
, ICMPV6_RS
, ICMPV6_RA
) < 0)
426 if (sk_setup_multicast(sk
) < 0)
429 if (sk_join_group(sk
, AllRouters
) < 0)