Exemple #1
0
ipv6_addr_t *gnrc_ipv6_netif_match_prefix(kernel_pid_t pid, const ipv6_addr_t *prefix)
{
    ipv6_addr_t *res = NULL;
    gnrc_ipv6_netif_t *iface = gnrc_ipv6_netif_get(pid);

    mutex_lock(&(iface->mutex));

    if (_find_by_prefix_unsafe(&res, iface, prefix, NULL) > 0) {
        mutex_unlock(&(iface->mutex));
        return res;
    }

    mutex_unlock(&(iface->mutex));

    return NULL;
}
Exemple #2
0
static ng_ipv6_addr_t *_match_prefix(kernel_pid_t pid, const ng_ipv6_addr_t *addr,
                                     bool only_unicast)
{
    ng_ipv6_addr_t *res = NULL;
    ng_ipv6_netif_t *iface = ng_ipv6_netif_get(pid);

    mutex_lock(&(iface->mutex));

    if (_find_by_prefix_unsafe(&res, iface, addr, only_unicast) > 0) {
        mutex_unlock(&(iface->mutex));
        return res;
    }

    mutex_unlock(&(iface->mutex));

    return NULL;
}
Exemple #3
0
kernel_pid_t ng_ipv6_netif_find_by_prefix(ng_ipv6_addr_t **out, const ng_ipv6_addr_t *prefix)
{
    uint8_t best_match = 0;
    ng_ipv6_addr_t *tmp_res = NULL;
    kernel_pid_t res = KERNEL_PID_UNDEF;

    for (int i = 0; i < NG_NETIF_NUMOF; i++) {
        uint8_t match;

        mutex_lock(&(ipv6_ifs[i].mutex));

        match = _find_by_prefix_unsafe(&tmp_res, ipv6_ifs + i, prefix, false);

        if (match > best_match) {
            if (out != NULL) {
                *out = tmp_res;
            }

            res = ipv6_ifs[i].pid;
            best_match = match;
        }

        mutex_unlock(&(ipv6_ifs[i].mutex));
    }

#if ENABLE_DEBUG

    if (res != KERNEL_PID_UNDEF) {
        DEBUG("Found %s on interface %" PRIkernel_pid " globally matching ",
              ng_ipv6_addr_to_str(addr_str, *out, sizeof(addr_str)),
              res);
        DEBUG("%s by %" PRIu8 " bits\n",
              ng_ipv6_addr_to_str(addr_str, prefix, sizeof(addr_str)),
              best_match);
    }
    else {
        DEBUG("Did not found any address globally matching %s\n",
              ng_ipv6_addr_to_str(addr_str, prefix, sizeof(addr_str)));
    }

#endif

    return res;
}
Exemple #4
0
/** @brief Find the best candidate among the configured addresses
 *          for a certain destination address according to the 8 rules
 *          specified in RFC 6734, section 5.
 * @see <a href="http://tools.ietf.org/html/rfc6724#section-5">
 *      RFC6724, section 5
 *      </a>
 *
 * @param[in] iface              The interface for sending.
 * @param[in] dst                The destination IPv6 address.
 * @param[in, out] candidate_set The preselected set of candidate addresses as
 *                               a bitfield.
 *
 * @pre @p dst is not unspecified.
 *
 * @return The best matching candidate found on @p iface, may be NULL if none
 *         is found.
 */
static ipv6_addr_t *_source_address_selection(gnrc_ipv6_netif_t *iface, const ipv6_addr_t *dst,
                                              uint8_t *candidate_set)
{
    /* create temporary set for assigning "points" to candidates wining in the
     * corresponding rules.
     */
    uint8_t winner_set[GNRC_IPV6_NETIF_ADDR_NUMOF];
    memset(winner_set, 0, GNRC_IPV6_NETIF_ADDR_NUMOF);

    uint8_t max_pts = 0;

    /* _create_candidate_set() assures that `dest` is not unspecified and if
     * `dst` is loopback rule 1 will fire anyway.  */
    uint8_t dst_scope = _get_scope(dst, true);
    DEBUG("finding the best match within the source address candidates\n");

    for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) {
        gnrc_ipv6_netif_addr_t *iter = &(iface->addrs[i]);
        DEBUG("Checking address: %s\n",
              ipv6_addr_to_str(addr_str, &(iter->addr), sizeof(addr_str)));
        /* entries which are not  part of the candidate set can be ignored */
        if (!(bf_isset(candidate_set, i))) {
            DEBUG("Not part of the candidate set - skipping\n");
            continue;
        }

        /* Rule 1: if we have an address configured that equals the destination
         * use this one as source */
        if (ipv6_addr_equal(&(iter->addr), dst)) {
            DEBUG("Ease one - rule 1\n");
            return &(iter->addr);
        }

        /* Rule 2: Prefer appropriate scope. */
        /* both link local */
        uint8_t candidate_scope = _get_scope(&(iter->addr), false);
        if (candidate_scope == dst_scope) {
            DEBUG("winner for rule 2 (same scope) found\n");
            winner_set[i] += RULE_2A_PTS;
            if (winner_set[i] > max_pts) {
                max_pts = RULE_2A_PTS;
            }
        }
        else if (candidate_scope < dst_scope) {
            DEBUG("winner for rule 2 (smaller scope) found\n");
            winner_set[i] += RULE_2B_PTS;
            if (winner_set[i] > max_pts) {
                max_pts = winner_set[i];
            }
        }

        /* Rule 3: Avoid deprecated addresses. */
        if (iter->preferred > 0) {
            DEBUG("winner for rule 3 found\n");
            winner_set[i] += RULE_3_PTS;
            if (winner_set[i] > max_pts) {
                max_pts = winner_set[i];
            }
        }

        /* Rule 4: Prefer home addresses.
         * Does not apply, gnrc does not support Mobile IP.
         * TODO: update as soon as gnrc supports Mobile IP
         */

        /* Rule 5: Prefer outgoing interface.
         * RFC 6724 says:
         * "It is RECOMMENDED that the candidate source addresses be the set of
         *  unicast addresses assigned to the interface that will be used to
         *  send to the destination (the "outgoing" interface).  On routers,
         *  the candidate set MAY include unicast addresses assigned to any
         *  interface that forwards packets, subject to the restrictions
         *  described below."
         *  Currently this implementation uses ALWAYS source addresses assigned
         *  to the outgoing interface. Hence, Rule 5 is always fulfilled.
         */

        /* Rule 6: Prefer matching label.
         * Flow labels are currently not supported by gnrc.
         * TODO: update as soon as gnrc supports flow labels
         */

        /* Rule 7: Prefer temporary addresses.
         * Temporary addresses are currently not supported by gnrc.
         * TODO: update as soon as gnrc supports temporary addresses
         */
    }

    /* reset candidate set to mark winners */
    memset(candidate_set, 0, (GNRC_IPV6_NETIF_ADDR_NUMOF / 8) + 1);
    /* check if we have a clear winner */
    /* collect candidates with maximum points */
    for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) {
        if (winner_set[i] == max_pts) {
            bf_set(candidate_set, i);
        }
    }

    /* otherwise apply rule 8: Use longest matching prefix. */
    ipv6_addr_t *res = NULL;
    _find_by_prefix_unsafe(&res, iface, dst, candidate_set);
    return res;
}