diff --git a/CHANGES b/CHANGES index 5a60b621..2d73c8e9 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +2016/09/18 Moved auto prefix code from config file parse to send_ra. + 2016/08/08 Merged ARPHRD_6LOWPAN netlink query from Add systemd service file diff --git a/gram.y b/gram.y index 1ed4aa33..9ee19d49 100644 --- a/gram.y +++ b/gram.y @@ -19,9 +19,6 @@ #include "defaults.h" #define YYERROR_VERBOSE 1 -static int countbits(int b); -static int count_mask(struct sockaddr_in6 *m); -static struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr const *mask); #if 0 /* no longer necessary? */ #ifndef HAVE_IN6_ADDR_S6_ADDR @@ -375,84 +372,12 @@ prefixdef : prefixhead optional_prefixplist ';' ABORT; } - if ( prefix->if6[0] && prefix->if6to4[0]) { - flog(LOG_ERR, "Base6Interface and Base6to4Interface are mutually exclusive at this time"); - ABORT; - } - - if ( prefix->if6to4[0] ) - { - if (get_v4addr(prefix->if6to4, &dst) < 0) - { - flog(LOG_ERR, "interface %s has no IPv4 addresses, disabling 6to4 prefix", prefix->if6to4 ); - prefix->enabled = 0; - } - else - { - *((uint16_t *)(prefix->Prefix.s6_addr)) = htons(0x2002); - memcpy( prefix->Prefix.s6_addr + 2, &dst, sizeof( dst ) ); - } - } - if ( prefix->if6[0] ) { -#ifndef HAVE_IFADDRS_H - flog(LOG_ERR, "Base6Interface not supported in %s, line %d", filename, num_lines); - ABORT; -#else - struct ifaddrs *ifap = 0, *ifa = 0; - struct AdvPrefix *next = prefix->next; - if (prefix->PrefixLen != 64) { flog(LOG_ERR, "only /64 is allowed with Base6Interface. %s:%d", filename, num_lines); ABORT; } - - if (getifaddrs(&ifap) != 0) - flog(LOG_ERR, "getifaddrs failed: %s", strerror(errno)); - - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - struct sockaddr_in6 *s6 = 0; - struct sockaddr_in6 *mask = (struct sockaddr_in6 *)ifa->ifa_netmask; - struct in6_addr base6prefix; - char buf[INET6_ADDRSTRLEN]; - int i; - - if (strncmp(ifa->ifa_name, prefix->if6, IFNAMSIZ)) - continue; - - if (ifa->ifa_addr->sa_family != AF_INET6) - continue; - - s6 = (struct sockaddr_in6 *)(ifa->ifa_addr); - - if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) - continue; - - base6prefix = get_prefix6(&s6->sin6_addr, &mask->sin6_addr); - for (i = 0; i < 8; ++i) { - prefix->Prefix.s6_addr[i] &= ~mask->sin6_addr.s6_addr[i]; - prefix->Prefix.s6_addr[i] |= base6prefix.s6_addr[i]; - } - memset(&prefix->Prefix.s6_addr[8], 0, 8); - prefix->AdvRouterAddr = 1; - prefix->AutoSelected = 1; - prefix->next = next; - - if (inet_ntop(ifa->ifa_addr->sa_family, (void *)&(prefix->Prefix), buf, sizeof(buf)) == NULL) - flog(LOG_ERR, "%s: inet_ntop failed in %s, line %d!", ifa->ifa_name, filename, num_lines); - else - dlog(LOG_DEBUG, 3, "auto-selected prefix %s/%d on interface %s from interface %s", - buf, prefix->PrefixLen, iface->props.name, ifa->ifa_name); - - /* Taking only one prefix from the Base6Interface. Taking more than one would require allocating new - prefixes and building a list. I'm not sure how to do that from here. So for now, break. */ - break; - } - - if (ifap) - freeifaddrs(ifap); -#endif /* ifndef HAVE_IFADDRS_H */ } } $$ = prefix; @@ -466,94 +391,26 @@ prefixhead : T_PREFIX IPV6ADDR '/' NUMBER memset(&zeroaddr, 0, sizeof(zeroaddr)); if (!memcmp($2, &zeroaddr, sizeof(struct in6_addr))) { -#ifndef HAVE_IFADDRS_H - flog(LOG_ERR, "invalid all-zeros prefix in %s, line %d", filename, num_lines); - ABORT; -#else - struct ifaddrs *ifap = 0, *ifa = 0; - struct AdvPrefix *next = iface->AdvPrefixList; - - while (next) { - if (next->AutoSelected) { - flog(LOG_ERR, "auto selecting prefixes works only once per interface. See %s, line %d", filename, num_lines); - ABORT; - } - next = next->next; - } - next = 0; - - dlog(LOG_DEBUG, 5, "all-zeros prefix in %s, line %d", filename, num_lines); - - if (getifaddrs(&ifap) != 0) - flog(LOG_ERR, "getifaddrs failed: %s", strerror(errno)); - - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr; - struct sockaddr_in6 *mask = (struct sockaddr_in6 *)ifa->ifa_netmask; - char buf[INET6_ADDRSTRLEN]; - - if (strncmp(ifa->ifa_name, iface->props.name, IFNAMSIZ)) - continue; - - if (ifa->ifa_addr->sa_family != AF_INET6) - continue; - - s6 = (struct sockaddr_in6 *)(ifa->ifa_addr); - - if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) - continue; - - prefix = malloc(sizeof(struct AdvPrefix)); - - if (prefix == NULL) { - flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); - ABORT; - } - - prefix_init_defaults(prefix); - prefix->Prefix = get_prefix6(&s6->sin6_addr, &mask->sin6_addr); - prefix->AdvRouterAddr = 1; - prefix->AutoSelected = 1; - prefix->next = next; - next = prefix; - - if (prefix->PrefixLen == 0) - prefix->PrefixLen = count_mask(mask); - - if (inet_ntop(ifa->ifa_addr->sa_family, (void *)&(prefix->Prefix), buf, sizeof(buf)) == NULL) - flog(LOG_ERR, "%s: inet_ntop failed in %s, line %d!", ifa->ifa_name, filename, num_lines); - else - dlog(LOG_DEBUG, 3, "auto-selected prefix %s/%d on interface %s", buf, prefix->PrefixLen, ifa->ifa_name); - } - - if (!prefix) { - flog(LOG_WARNING, "no auto-selected prefix on interface %s, disabling advertisements", iface->props.name); - } - - if (ifap) - freeifaddrs(ifap); -#endif /* ifndef HAVE_IFADDRS_H */ + flog(LOG_WARNING, "invalid all-zeros prefix in %s, line %d", filename, num_lines); } - else { - prefix = malloc(sizeof(struct AdvPrefix)); + prefix = malloc(sizeof(struct AdvPrefix)); - if (prefix == NULL) { - flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); - ABORT; - } + if (prefix == NULL) { + flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); + ABORT; + } - prefix_init_defaults(prefix); + prefix_init_defaults(prefix); - if ($4 > MAX_PrefixLen) - { - flog(LOG_ERR, "invalid prefix length in %s, line %d", filename, num_lines); - ABORT; - } + if ($4 > MAX_PrefixLen) + { + flog(LOG_ERR, "invalid prefix length in %s, line %d", filename, num_lines); + ABORT; + } - prefix->PrefixLen = $4; + prefix->PrefixLen = $4; - memcpy(&prefix->Prefix, $2, sizeof(struct in6_addr)); - } + memcpy(&prefix->Prefix, $2, sizeof(struct in6_addr)); } ; @@ -569,72 +426,33 @@ prefixplist : prefixplist prefixparms prefixparms : T_AdvOnLink SWITCH ';' { if (prefix) { - if (prefix->AutoSelected) { - struct AdvPrefix *p = prefix; - do { - p->AdvOnLinkFlag = $2; - p = p->next; - } while (p && p->AutoSelected); - } - else - prefix->AdvOnLinkFlag = $2; + prefix->AdvOnLinkFlag = $2; } } | T_AdvAutonomous SWITCH ';' { if (prefix) { - if (prefix->AutoSelected) { - struct AdvPrefix *p = prefix; - do { - p->AdvAutonomousFlag = $2; - p = p->next; - } while (p && p->AutoSelected); - } - else - prefix->AdvAutonomousFlag = $2; + prefix->AdvAutonomousFlag = $2; } } | T_AdvRouterAddr SWITCH ';' { if (prefix) { - if (prefix->AutoSelected && $2 == 0) - flog(LOG_WARNING, "prefix automatically selected, AdvRouterAddr always enabled, ignoring config line %d", num_lines); - else - prefix->AdvRouterAddr = $2; + prefix->AdvRouterAddr = $2; } } | T_AdvValidLifetime number_or_infinity ';' { if (prefix) { - if (prefix->AutoSelected) { - struct AdvPrefix *p = prefix; - do { - p->AdvValidLifetime = $2; - p->curr_validlft = $2; - p = p->next; - } while (p && p->AutoSelected); - } - else { - prefix->AdvValidLifetime = $2; - prefix->curr_validlft = $2; - } + prefix->AdvValidLifetime = $2; + prefix->curr_validlft = $2; } } | T_AdvPreferredLifetime number_or_infinity ';' { if (prefix) { - if (prefix->AutoSelected) { - struct AdvPrefix *p = prefix; - do { - p->AdvPreferredLifetime = $2; - p->curr_preferredlft = $2; - p = p->next; - } while (p && p->AutoSelected); - } - else { - prefix->AdvPreferredLifetime = $2; - prefix->curr_preferredlft = $2; - } + prefix->AdvPreferredLifetime = $2; + prefix->curr_preferredlft = $2; } } | T_DeprecatePrefix SWITCH ';' @@ -651,28 +469,30 @@ prefixparms : T_AdvOnLink SWITCH ';' } | T_Base6Interface name ';' { +#ifndef HAVE_IFADDRS_H + flog(LOG_ERR, "Base6Interface not supported in %s, line %d", filename, num_lines); + ABORT; +#else if (prefix) { - if (prefix->AutoSelected) { - flog(LOG_ERR, "automatically selecting the prefix and Base6Interface are mutually exclusive"); - ABORT; - } /* fallthrough */ dlog(LOG_DEBUG, 4, "using prefixes on interface %s for prefixes on interface %s", $2, iface->props.name); strncpy(prefix->if6, $2, IFNAMSIZ-1); prefix->if6[IFNAMSIZ-1] = '\0'; } +#endif } | T_Base6to4Interface name ';' { +#ifndef HAVE_IFADDRS_H + flog(LOG_ERR, "Base6to4Interface not supported in %s, line %d", filename, num_lines); + ABORT; +#else if (prefix) { - if (prefix->AutoSelected) { - flog(LOG_ERR, "automatically selecting the prefix and Base6to4Interface are mutually exclusive"); - ABORT; - } /* fallthrough */ dlog(LOG_DEBUG, 4, "using interface %s for 6to4 prefixes on interface %s", $2, iface->props.name); strncpy(prefix->if6to4, $2, IFNAMSIZ-1); prefix->if6to4[IFNAMSIZ-1] = '\0'; } +#endif } ; @@ -1036,41 +856,6 @@ number_or_infinity : NUMBER %% -static int countbits(int b) -{ - int count; - - for (count = 0; b != 0; count++) { - b &= b - 1; // this clears the LSB-most set bit - } - - return (count); -} - -static int count_mask(struct sockaddr_in6 *m) -{ - struct in6_addr *in6 = &m->sin6_addr; - int i; - int count = 0; - - for (i = 0; i < 16; ++i) { - count += countbits(in6->s6_addr[i]); - } - return count; -} - -static struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr const *mask) -{ - struct in6_addr prefix = *addr; - int i = 0; - - for (; i < 16; ++i) { - prefix.s6_addr[i] &= mask->s6_addr[i]; - } - - return prefix; -} - static void cleanup(void) { if (iface) { diff --git a/interface.c b/interface.c index d09a1e71..56c3d677 100644 --- a/interface.c +++ b/interface.c @@ -113,8 +113,6 @@ void prefix_init_defaults(struct AdvPrefix *prefix) prefix->AdvPreferredLifetime = DFLT_AdvPreferredLifetime; prefix->DeprecatePrefixFlag = DFLT_DeprecatePrefixFlag; prefix->DecrementLifetimesFlag = DFLT_DecrementLifetimesFlag; - prefix->if6to4[0] = 0; - prefix->enabled = 1; prefix->curr_validlft = prefix->AdvValidLifetime; prefix->curr_preferredlft = prefix->AdvPreferredLifetime; diff --git a/process.c b/process.c index 1e392c73..c9b9b36a 100644 --- a/process.c +++ b/process.c @@ -255,7 +255,7 @@ static void process_ra(struct Interface *iface, unsigned char *msg, int len, str struct AdvPrefix *prefix = iface->AdvPrefixList; while (prefix) { char prefix_str[INET6_ADDRSTRLEN]; - if (prefix->enabled && (prefix->PrefixLen == pinfo->nd_opt_pi_prefix_len) + if ((prefix->PrefixLen == pinfo->nd_opt_pi_prefix_len) && addr_match(&prefix->Prefix, &pinfo->nd_opt_pi_prefix, prefix->PrefixLen)) { addrtostr(&prefix->Prefix, prefix_str, sizeof(prefix_str)); diff --git a/radvd.h b/radvd.h index 08b8181b..12e403ca 100644 --- a/radvd.h +++ b/radvd.h @@ -144,8 +144,6 @@ struct AdvPrefix { /* 6to4 etc. extensions */ char if6to4[IFNAMSIZ]; - int enabled; - int AutoSelected; /* Select prefixes from this interface. */ char if6[IFNAMSIZ]; @@ -310,6 +308,9 @@ void process(int sock, struct Interface *, unsigned char *, int, struct sockaddr int recv_rs_ra(int sock, unsigned char *, struct sockaddr_in6 *, struct in6_pktinfo **, int *, unsigned char*); /* util.c */ +int countbits(int b); +int count_mask(struct sockaddr_in6 *m); +struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr const *mask); char * strdupf(char const * format, ...) __attribute__ ((format(printf, 1, 2))); double rand_between(double, double); int check_dnssl_presence(struct AdvDNSSL *, const char *); diff --git a/send.c b/send.c index 96ded058..bbd7a23a 100644 --- a/send.c +++ b/send.c @@ -26,7 +26,8 @@ static void decrement_lifetime(const time_t secs, uint32_t * lifetime); static void update_iface_times(struct Interface * iface); static void add_ra_header(struct safe_buffer * sb, struct ra_header_info const * ra_header_info, int cease_adv); -static void add_prefix(struct safe_buffer * sb, struct AdvPrefix const * prefix, int cease_adv); +static void add_prefixs(struct safe_buffer * sb, char const * ifname, struct AdvPrefix const * prefix, int cease_adv); +static void add_one_prefix(struct safe_buffer * sb, char const * ifname, struct AdvPrefix const * prefix, int cease_adv); static void add_route(struct safe_buffer * sb, struct AdvRoute const *route, int cease_adv); static void add_rdnss(struct safe_buffer * sb, struct AdvRDNSS const *rdnss, int cease_adv); static size_t serialize_domain_names(struct safe_buffer * safe_buffer, struct AdvDNSSL const *dnssl); @@ -138,7 +139,7 @@ static void update_iface_times(struct Interface * iface) struct AdvPrefix *prefix = iface->AdvPrefixList; while (prefix) { - if (prefix->enabled && (!prefix->DecrementLifetimesFlag || prefix->curr_preferredlft > 0)) { + if ((!prefix->DecrementLifetimesFlag || prefix->curr_preferredlft > 0)) { if (!(iface->state_info.cease_adv && prefix->DeprecatePrefixFlag)) { if (prefix->DecrementLifetimesFlag) { @@ -191,39 +192,130 @@ static void add_ra_header(struct safe_buffer * sb, struct ra_header_info const * safe_buffer_append(sb, &radvert, sizeof(radvert)); } -static void add_prefix(struct safe_buffer * sb, struct AdvPrefix const *prefix, int cease_adv) +static void add_one_prefix(struct safe_buffer * sb, char const * ifname, struct AdvPrefix const * prefix, int cease_adv) +{ + struct nd_opt_prefix_info pinfo; + + memset(&pinfo, 0, sizeof(pinfo)); + + pinfo.nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; + pinfo.nd_opt_pi_len = 4; + pinfo.nd_opt_pi_prefix_len = prefix->PrefixLen; + + pinfo.nd_opt_pi_flags_reserved = (prefix->AdvOnLinkFlag) ? ND_OPT_PI_FLAG_ONLINK : 0; + pinfo.nd_opt_pi_flags_reserved |= (prefix->AdvAutonomousFlag) ? ND_OPT_PI_FLAG_AUTO : 0; + /* Mobile IPv6 ext */ + pinfo.nd_opt_pi_flags_reserved |= (prefix->AdvRouterAddr) ? ND_OPT_PI_FLAG_RADDR : 0; + + if (cease_adv && prefix->DeprecatePrefixFlag) { + /* RFC4862, 5.5.3, step e) */ + if (prefix->curr_validlft < MIN_AdvValidLifetime) { + pinfo.nd_opt_pi_valid_time = htonl(prefix->curr_validlft); + } else { + pinfo.nd_opt_pi_valid_time = htonl(MIN_AdvValidLifetime); + } + pinfo.nd_opt_pi_preferred_time = 0; + } else { + pinfo.nd_opt_pi_valid_time = htonl(prefix->curr_validlft); + pinfo.nd_opt_pi_preferred_time = htonl(prefix->curr_preferredlft); + } + + memcpy(&pinfo.nd_opt_pi_prefix, &prefix->Prefix, sizeof(struct in6_addr)); + + safe_buffer_append(sb, &pinfo, sizeof(pinfo)); +} +static void add_auto_prefixes_6to4(struct safe_buffer * sb, char const * ifname, struct AdvPrefix const *prefix, int cease_adv) +{ +#ifdef HAVE_IFADDRS_H + struct AdvPrefix xprefix = *prefix; + unsigned int dst; + if (get_v4addr(prefix->if6to4, &dst) < 0) { + flog(LOG_ERR, "Base6to4interface %s has no IPv4 addresses", prefix->if6to4); + } else { + memcpy(xprefix.Prefix.s6_addr + 2, &dst, sizeof(dst)); + *((uint16_t *)(xprefix.Prefix.s6_addr)) = htons(0x2002); + xprefix.PrefixLen = 64; + + char pfx_str[INET6_ADDRSTRLEN]; + addrtostr(&xprefix.Prefix, pfx_str, sizeof(pfx_str)); + dlog(LOG_DEBUG, 3, "auto-selected prefix %s/%d on interface %s", + pfx_str, xprefix.PrefixLen, ifname); + + /* TODO: Something must be done with these. */ + (void)xprefix.curr_validlft; + (void)xprefix.curr_preferredlft; + + add_one_prefix(sb, ifname, &xprefix, cease_adv); + } +#endif +} + + +static void add_auto_prefixes(struct safe_buffer * sb, char const * ifname, struct AdvPrefix const *prefix, int cease_adv) +{ +#ifdef HAVE_IFADDRS_H + struct AdvPrefix xprefix; + struct ifaddrs *ifap = 0, *ifa = 0; + + if (getifaddrs(&ifap) != 0) + flog(LOG_ERR, "getifaddrs failed: %s", strerror(errno)); + + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + + if (strncmp(ifa->ifa_name, ifname, IFNAMSIZ)) + continue; + + if (ifa->ifa_addr->sa_family != AF_INET6) + continue; + + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr; + struct sockaddr_in6 *mask = (struct sockaddr_in6 *)ifa->ifa_netmask; + + if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) + continue; + + xprefix = *prefix; + xprefix.Prefix = get_prefix6(&s6->sin6_addr, &mask->sin6_addr); + xprefix.PrefixLen = count_mask(mask); + + char pfx_str[INET6_ADDRSTRLEN]; + addrtostr(&xprefix.Prefix, pfx_str, sizeof(pfx_str)); + dlog(LOG_DEBUG, 3, "auto-selected prefix %s/%d on interface %s", + pfx_str, xprefix.PrefixLen, ifname); + + /* TODO: Something must be done with these. */ + (void)xprefix.curr_validlft; + (void)xprefix.curr_preferredlft; + + add_one_prefix(sb, ifname, &xprefix, cease_adv); + } + + if (ifap) + freeifaddrs(ifap); +#endif +} + +static void add_prefixs(struct safe_buffer * sb, char const * ifname, struct AdvPrefix const *prefix, int cease_adv) { while (prefix) { - if (prefix->enabled && (!prefix->DecrementLifetimesFlag || prefix->curr_preferredlft > 0)) { - struct nd_opt_prefix_info pinfo; - - memset(&pinfo, 0, sizeof(pinfo)); - - pinfo.nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; - pinfo.nd_opt_pi_len = 4; - pinfo.nd_opt_pi_prefix_len = prefix->PrefixLen; - - pinfo.nd_opt_pi_flags_reserved = (prefix->AdvOnLinkFlag) ? ND_OPT_PI_FLAG_ONLINK : 0; - pinfo.nd_opt_pi_flags_reserved |= (prefix->AdvAutonomousFlag) ? ND_OPT_PI_FLAG_AUTO : 0; - /* Mobile IPv6 ext */ - pinfo.nd_opt_pi_flags_reserved |= (prefix->AdvRouterAddr) ? ND_OPT_PI_FLAG_RADDR : 0; - - if (cease_adv && prefix->DeprecatePrefixFlag) { - /* RFC4862, 5.5.3, step e) */ - if (prefix->curr_validlft < MIN_AdvValidLifetime) { - pinfo.nd_opt_pi_valid_time = htonl(prefix->curr_validlft); - } else { - pinfo.nd_opt_pi_valid_time = htonl(MIN_AdvValidLifetime); + if ((!prefix->DecrementLifetimesFlag || prefix->curr_preferredlft > 0)) { + struct in6_addr zero = {}; + if (prefix->if6to4[0] || prefix->if6[0] || 0 == memcmp(&prefix->Prefix, &zero, sizeof(zero))) { + if (prefix->if6to4[0]) { + dlog(LOG_DEBUG, 4, "if6to4 auto prefix detected on iface %s", ifname); + add_auto_prefixes_6to4(sb, prefix->if6to4, prefix, cease_adv); + } + if (prefix->if6[0]) { + dlog(LOG_DEBUG, 4, "if6 auto prefix detected on iface %s", ifname); + add_auto_prefixes(sb, prefix->if6, prefix, cease_adv); + } + if (0 == memcmp(&prefix->Prefix, &zero, sizeof(zero))) { + dlog(LOG_DEBUG, 4, "::/64 auto prefix detected on iface %s", ifname); + add_auto_prefixes(sb, ifname, prefix, cease_adv); } - pinfo.nd_opt_pi_preferred_time = 0; } else { - pinfo.nd_opt_pi_valid_time = htonl(prefix->curr_validlft); - pinfo.nd_opt_pi_preferred_time = htonl(prefix->curr_preferredlft); + add_one_prefix(sb, ifname, prefix, cease_adv); } - - memcpy(&pinfo.nd_opt_pi_prefix, &prefix->Prefix, sizeof(struct in6_addr)); - - safe_buffer_append(sb, &pinfo, sizeof(pinfo)); } prefix = prefix->next; @@ -579,7 +671,7 @@ static void build_ra(struct safe_buffer * sb, struct Interface const * iface) add_ra_header(sb, &iface->ra_header_info, iface->state_info.cease_adv); if (iface->AdvPrefixList) { - add_prefix(sb, iface->AdvPrefixList, iface->state_info.cease_adv); + add_prefixs(sb, iface->props.name, iface->AdvPrefixList, iface->state_info.cease_adv); } if (iface->AdvRouteList) { diff --git a/test/send.c b/test/send.c index 5a9f7108..1da8d5f8 100644 --- a/test/send.c +++ b/test/send.c @@ -61,7 +61,7 @@ START_TEST (test_add_prefix) ck_assert_ptr_ne(0, iface); struct safe_buffer sb = SAFE_BUFFER_INIT; - add_prefix(&sb, iface->AdvPrefixList, iface->state_info.cease_adv); + add_prefixs(&sb, iface->props.name, iface->AdvPrefixList, iface->state_info.cease_adv); #ifdef PRINT_SAFE_BUFFER print_safe_buffer(&sb); diff --git a/util.c b/util.c index b4b4620e..30fdb1aa 100644 --- a/util.c +++ b/util.c @@ -171,3 +171,40 @@ ssize_t writen(int fd, const void *buf, size_t count) } return n; } + +int countbits(int b) +{ + int count; + + for (count = 0; b != 0; count++) { + b &= b - 1; // this clears the LSB-most set bit + } + + return (count); +} + +int count_mask(struct sockaddr_in6 *m) +{ + struct in6_addr *in6 = &m->sin6_addr; + int i; + int count = 0; + + for (i = 0; i < 16; ++i) { + count += countbits(in6->s6_addr[i]); + } + return count; +} + +struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr const *mask) +{ + struct in6_addr prefix = *addr; + int i = 0; + + for (; i < 16; ++i) { + prefix.s6_addr[i] &= mask->s6_addr[i]; + } + + return prefix; +} + +