/* * BIRD -- RAdv Packet Processing * * * Can be freely distributed and used under the terms of the GNU GPL. */ #include #include "radv.h" struct radv_ra_packet { u8 type; u8 code; u16 checksum; u8 current_hop_limit; u8 flags; u16 router_lifetime; u32 reachable_time; u32 retrans_timer; }; #define OPT_RA_MANAGED 0x80 #define OPT_RA_OTHER_CFG 0x40 #define OPT_PREFIX 3 #define OPT_MTU 5 #define OPT_RDNSS 25 #define OPT_DNSSL 31 struct radv_opt_prefix { u8 type; u8 length; u8 pxlen; u8 flags; u32 valid_lifetime; u32 preferred_lifetime; u32 reserved; ip_addr prefix; }; #define OPT_PX_ONLINK 0x80 #define OPT_PX_AUTONOMOUS 0x40 struct radv_opt_mtu { u8 type; u8 length; u16 reserved; u32 mtu; }; struct radv_opt_rdnss { u8 type; u8 length; u16 reserved; u32 lifetime; ip_addr servers[]; }; struct radv_opt_dnssl { u8 type; u8 length; u16 reserved; u32 lifetime; char domain[]; }; static int radv_prepare_rdnss(struct radv_iface *ifa, list *rdnss_list, char **buf, char *bufend) { struct radv_rdnss_config *rcf = HEAD(*rdnss_list); while(NODE_VALID(rcf)) { struct radv_rdnss_config *rcf_base = rcf; struct radv_opt_rdnss *op = (void *) *buf; int max_i = (bufend - *buf - sizeof(struct radv_opt_rdnss)) / sizeof(ip_addr); int i = 0; if (max_i < 1) goto too_much; op->type = OPT_RDNSS; op->reserved = 0; if (rcf->lifetime_mult) op->lifetime = htonl(rcf->lifetime_mult * ifa->cf->max_ra_int); else op->lifetime = htonl(rcf->lifetime); while(NODE_VALID(rcf) && (rcf->lifetime == rcf_base->lifetime) && (rcf->lifetime_mult == rcf_base->lifetime_mult)) { if (i >= max_i) goto too_much; op->servers[i] = rcf->server; ipa_hton(op->servers[i]); i++; rcf = NODE_NEXT(rcf); } op->length = 1+2*i; *buf += 8 * op->length; } return 0; too_much: log(L_WARN "%s: Too many RA options on interface %s", ifa->ra->p.name, ifa->iface->name); return -1; } int radv_process_domain(struct radv_dnssl_config *cf) { /* Format of domain in search list is