Ejemplo n.º 1
0
void process_new_gateway (
    lisp_addr_t         gateway,
    lispd_iface_elt     *iface )
{
    lisp_addr_t **gw_addr   = NULL;
    int         afi         = AF_UNSPEC;


    switch(gateway.afi) {
    case AF_INET:
        gw_addr = &(iface->ipv4_gateway);
        afi = AF_INET;
        break;
    case AF_INET6:
        gw_addr = &(iface->ipv6_gateway);
        afi = AF_INET6;
        break;
    default:
        return;
    }
    if (*gw_addr == NULL) { // The default gateway of this interface is not deffined yet
        *gw_addr = clone_lisp_addr(&gateway);
        if (*gw_addr == NULL) {
            free (*gw_addr);
            *gw_addr = NULL;
            return;
        }
    } else {
        copy_lisp_addr(*gw_addr,&gateway);
    }

    add_route(afi,iface->iface_index,NULL,NULL,*gw_addr,0,100,iface->iface_index);
}
Ejemplo n.º 2
0
/*
 * Copy address into a new generated lisp_addr_t structure
 * @param addr Address to be copied
 * @return New allocated address
 */
lisp_addr_t *clone_lisp_addr(lisp_addr_t *addr)
{
    lisp_addr_t *new_addr = NULL;

    if ((new_addr = (lisp_addr_t *)malloc(sizeof(lisp_addr_t))) == NULL) {
        lispd_log_msg(LISP_LOG_WARNING, "clone_lisp_addr: Unable to allocate memory for lisp_addr_t: %s", strerror(errno));
        return(NULL);
    }

    copy_lisp_addr(new_addr, addr);
    if (new_addr->afi == AF_UNSPEC){
        lispd_log_msg(LISP_LOG_DEBUG_1, "clone_lisp_addr: Unknown AFI: %d.", addr->afi);
        free (new_addr);
        new_addr = NULL;
    }

    return (new_addr);
}
Ejemplo n.º 3
0
int lispd_get_iface_address(
    char                *ifacename,
    lisp_addr_t         *addr,
    int                 afi)
{
    struct ifaddrs      *ifaddr;
    struct ifaddrs      *ifa;
    struct sockaddr_in  *s4;
    struct sockaddr_in6 *s6;
    lisp_addr_t         ip;
    char addr_str[MAX_INET_ADDRSTRLEN];


    if (default_rloc_afi != -1){ /* If forced a exact RLOC type (Just IPv4 of just IPv6) */
        if(afi != default_rloc_afi){
            lispd_log_msg(LISP_LOG_INFO,"Default RLOC afi defined: Skipped %s address in iface %s",
                          (afi == AF_INET) ? "IPv4" : "IPv6",ifacename);
            return (BAD);
        }
    }

    /* 
     * make sure this is clean
     */

    memset(addr, 0, sizeof(lisp_addr_t));

    /*
     *  go search for the interface
     */

    if (getifaddrs(&ifaddr) !=0) {
        lispd_log_msg(LISP_LOG_DEBUG_2,
               "lispd_get_iface_address: getifaddrs error: %s", strerror(errno));
        return(BAD);
    }

    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
        if ((ifa->ifa_addr == NULL) || ((ifa->ifa_flags & IFF_UP) == 0) || (ifa->ifa_addr->sa_family != afi))
            continue;

        switch (ifa->ifa_addr->sa_family) {
        case AF_INET:
            s4 = (struct sockaddr_in *)(ifa->ifa_addr);
            if (strcmp(ifa->ifa_name, ifacename) == 0) {
                memcpy((void *) &(ip.address),
                       (void *)&(s4->sin_addr), sizeof(struct in_addr));
                ip.afi = AF_INET;
                if (is_link_local_addr(ip) != TRUE){
                    copy_lisp_addr(addr,&ip);
                }else{
                    lispd_log_msg(LISP_LOG_DEBUG_2, "lispd_get_iface_address: interface address from %s discarded (%s)",
                            ifacename, get_char_from_lisp_addr_t(ip));
                    continue;
                }
                lispd_log_msg(LISP_LOG_DEBUG_2, "lispd_get_iface_address: IPv4 RLOC from interface (%s): %s \n",
                        ifacename,
                        inet_ntop(AF_INET, &(s4->sin_addr),
                            addr_str, MAX_INET_ADDRSTRLEN));
                freeifaddrs(ifaddr);
                return(GOOD);
            } else {
                continue;
            }
        case AF_INET6:
            s6 = (struct sockaddr_in6 *)(ifa->ifa_addr);
            // XXX sin6_scope_id is an ID depending on the scope of the address.  Linux only supports it for link-
            // local addresses, in that case sin6_scope_id contains the interface index. --> If sin6_scope_id is
            // not zero, is a link-local address
            if (s6->sin6_scope_id != 0){
                lispd_log_msg(LISP_LOG_DEBUG_2, "lispd_get_iface_address: interface address from %s discarded (%s)",
                        ifacename, inet_ntop(AF_INET6, &(s6->sin6_addr), addr_str, MAX_INET_ADDRSTRLEN));
                continue;
            }
            if (!strcmp(ifa->ifa_name, ifacename)) {
                memcpy((void *) &(addr->address),
                       (void *)&(s6->sin6_addr),
                       sizeof(struct in6_addr));
                addr->afi = AF_INET6;
                lispd_log_msg(LISP_LOG_DEBUG_2, "lispd_get_iface_address: IPv6 RLOC from interface (%s): %s\n",
                        ifacename, 
                        inet_ntop(AF_INET6, &(s6->sin6_addr), 
                            addr_str, MAX_INET_ADDRSTRLEN));
                freeifaddrs(ifaddr);
                return(GOOD);
            } else {
                continue;
            }
        default:
            continue;                   /* XXX */
        }
    }
    freeifaddrs(ifaddr);
    lispd_log_msg(LISP_LOG_DEBUG_3, "lispd_get_iface_address: No %s RLOC configured for interface %s\n",
            (afi == AF_INET) ? "IPv4" : "IPv6",
            ifacename);
    return(BAD);
}
Ejemplo n.º 4
0
void process_address_change (
    lispd_iface_elt     *iface,
    lisp_addr_t         new_addr)
{
    lisp_addr_t                 *iface_addr         = NULL;
    lispd_iface_mappings_list   *mapping_list       = NULL;
    int                         aux_afi             = 0;

    // XXX To be modified when full NAT implemented --> When Nat Aware active no IPv6 RLOCs supported
    if (nat_aware == TRUE && new_addr.afi == AF_INET6) {
        return;
    }

    /* Check if the addres is a global address*/
    if (is_link_local_addr(new_addr) == TRUE) {
        lispd_log_msg(LISP_LOG_DEBUG_2,"precess_address_change: the extractet address from the netlink "
                      "messages is a local link address: %s discarded", get_char_from_lisp_addr_t(new_addr));
        return;
    }
    /* If default RLOC afi defined (-a 4 or 6), only accept addresses of the specified afi */
    if (default_rloc_afi != AF_UNSPEC && default_rloc_afi != new_addr.afi) {
        lispd_log_msg(LISP_LOG_DEBUG_2,"precess_address_change: Default RLOC afi defined (-a #): Skipped %s address in iface %s",
                      (new_addr.afi == AF_INET) ? "IPv4" : "IPv6",iface->iface_name);
        return;
    }
    /*
     * Actions to be done due to a change of address: SMR
     */

    switch (new_addr.afi) {
    case AF_INET:
        iface_addr = iface->ipv4_address;
        break;
    case AF_INET6:
        iface_addr = iface->ipv6_address;
        break;
    }

    // Same address that we already have
    if (compare_lisp_addr_t(iface_addr,&new_addr)==0) {
        lispd_log_msg(LISP_LOG_DEBUG_2,"precess_address_change: The detected change of address for interface %s "
                      "doesn't affect",iface->iface_name);
        /* We must rebind the socket just in case the address is from a virtual interface who has changed its interafce number */
        switch (new_addr.afi) {
        case AF_INET:
            bind_socket_src_address(iface->out_socket_v4,&new_addr);
            break;
        case AF_INET6:
            bind_socket_src_address(iface->out_socket_v6,&new_addr);
            break;
        }

        return;
    }

    /*
     * Change source routing rules for this interface and binding
     */

    if (iface_addr->afi != AF_UNSPEC) {
        del_rule(iface_addr->afi,
                 0,
                 iface->iface_index,
                 iface->iface_index,
                 RTN_UNICAST,
                 iface_addr,
                 (iface_addr->afi == AF_INET) ? 32 : 128,
                 NULL,0,0);
    }
    add_rule(new_addr.afi,
             0,
             iface->iface_index,
             iface->iface_index,
             RTN_UNICAST,
             &new_addr,
             (new_addr.afi == AF_INET) ? 32 : 128,
             NULL,0,0);

    switch (new_addr.afi) {
    case AF_INET:
        bind_socket_src_address(iface->out_socket_v4,&new_addr);
        break;
    case AF_INET6:
        bind_socket_src_address(iface->out_socket_v6,&new_addr);
        break;
    }


    aux_afi = iface_addr->afi;
    // Update the new address
    copy_lisp_addr(iface_addr, &new_addr);


    /* The interface was down during initial configuratiopn process and now it is up. Activate address */
    if (aux_afi == AF_UNSPEC) {
        lispd_log_msg(LISP_LOG_DEBUG_1,"process_address_change: Activating the locator address %s"
                      , get_char_from_lisp_addr_t(new_addr));
        activate_interface_address(iface, new_addr);
        if (iface->status == UP) {
            iface_balancing_vectors_calc(iface);

            /*
             * If no default control and data interface, recalculate it
             */

            if ((default_ctrl_iface_v4 == NULL && new_addr.afi == AF_INET) ||
                    (default_ctrl_iface_v6 == NULL && new_addr.afi == AF_INET6)) {
                lispd_log_msg(LISP_LOG_DEBUG_2,"No default control interface. Recalculate new control interface");
                set_default_ctrl_ifaces();
            }

            if ((default_out_iface_v4 == NULL && new_addr.afi == AF_INET) ||
                    (default_out_iface_v6 == NULL && new_addr.afi == AF_INET6)) {
                lispd_log_msg(LISP_LOG_DEBUG_2,"No default output interface. Recalculate new output interface");
                set_default_output_ifaces();
            }
        }
    }

    lispd_log_msg(LISP_LOG_DEBUG_1,"precess_address_change: New address detected for interface %s -> %s",
                  iface->iface_name, get_char_from_lisp_addr_t(new_addr));

    mapping_list = iface->head_mappings_list;
    /* Sort again the locators list of the affected mappings*/
    while (mapping_list != NULL) {
        if (aux_afi != AF_UNSPEC && // When the locator is activated, it is automatically sorted
                ((new_addr.afi == AF_INET && mapping_list->use_ipv4_address == TRUE) ||
                 (new_addr.afi == AF_INET6 && mapping_list->use_ipv6_address == TRUE))) {
            sort_locators_list_elt (mapping_list->mapping, iface_addr);
        }
        mapping_list = mapping_list->next;
    }

    /* Indicate change of address in the interface */

    switch (new_addr.afi) {
    case AF_INET:
        iface->ipv4_changed = TRUE;
        break;
    case AF_INET6:
        iface->ipv6_changed = TRUE;
        break;
    }


    /* If it is compiled in router mode, then recompile default routes changing the indicated src address*/

    if (router_mode == TRUE) {
        switch (new_addr.afi) {
        case AF_INET:
            if (iface == default_out_iface_v4) {
                set_tun_default_route_v4();
            }
            break;
        case AF_INET6:
            if (iface == default_out_iface_v6) {
                del_tun_default_route_v6();
                set_tun_default_route_v6();
            }
            break;
        }
    }

    /* Check if the new address is behind NAT */

    if(nat_aware==TRUE) {
        // TODO : To be modified when implementing NAT per multiple interfaces
        nat_status = UNKNOWN;
        clear_rtr_from_locators (iface);

        if (iface->status == UP) {
            initial_info_request_process();
        } else {
            nat_aware_iface_address_change = TRUE;
        }
    }

    /* Reprograming SMR timer*/
    if (smr_timer == NULL) {
        smr_timer = create_timer (SMR_TIMER);
    }

    start_timer(smr_timer, LISPD_SMR_TIMEOUT,(timer_callback)init_smr, NULL);
}
Ejemplo n.º 5
0
void process_new_gateway (
        lisp_addr_t         gateway,
        lispd_iface_elt     *iface )
{
    lisp_addr_t                 **gw_addr    = NULL;
    int                         afi          = AF_UNSPEC;
    lispd_mapping_list          *map_list    = NULL;


    switch(gateway.afi){
    case AF_INET:
        gw_addr = &(iface->ipv4_gateway);
        afi = AF_INET;
        iface->ipv4_changed = TRUE;
        break;
    case AF_INET6:
        gw_addr = &(iface->ipv6_gateway);
        afi = AF_INET6;
        iface->ipv6_changed = TRUE;
        break;
    default:
        return;
    }
    if (*gw_addr == NULL){ // The default gateway of this interface is not deffined yet
        *gw_addr = clone_lisp_addr(&gateway);
        if (*gw_addr == NULL){
            free (*gw_addr);
            *gw_addr = NULL;
            return;
        }
    }else{
        copy_lisp_addr(*gw_addr,&gateway);
    }
#ifndef VPNAPI
    add_route(afi,iface->iface_index,NULL,NULL,*gw_addr,0,100,iface->iface_index);
#endif

#ifdef VPNAPI
    if (iface->status != UP){
        lispd_log_msg(LISP_LOG_DEBUG_1,"process_new_gateway: Probably the interface %s is UP "
                "but we didn't receive netlink indicating this. Change %s status to UP",
                iface->iface_name,iface->iface_name);
        iface->status = UP;

        /*
         * If we don't have default control or output iface, recalculate it
         */

        if ((default_ctrl_iface_v4 == NULL && iface->ipv4_address->afi != AF_UNSPEC) ||
                (default_ctrl_iface_v6 == NULL && iface->ipv6_address->afi != AF_UNSPEC)){
            lispd_log_msg(LISP_LOG_DEBUG_2,"process_new_gateway: Recalculate new control interface");
            set_default_ctrl_ifaces();
        }

        if ((default_out_iface_v4 == NULL && iface->ipv4_address->afi != AF_UNSPEC) ||
                (default_out_iface_v6 == NULL && iface->ipv6_address->afi != AF_UNSPEC)){
            lispd_log_msg(LISP_LOG_DEBUG_2,"process_new_gateway: Recalculate new data interface");
            set_default_output_ifaces();
        }
    }

    if (gateway.afi == AF_INET){
        reset_socket(ipv4_data_input_fd);
        reset_socket(ipv4_control_input_fd);
    }else{
        reset_socket(ipv6_data_input_fd);
        reset_socket(ipv6_control_input_fd);
    }
#endif

    /* Check if the interface is behind NAT */

    if(nat_aware==TRUE){
        if (iface->status == UP && iface->ipv4_address != NULL){
            map_list = get_mappings_from_iface(iface);
            restart_info_request_process(map_list,iface->ipv4_address);
            free_mapping_list(map_list,FALSE);
        }
    }

    /* Reprograming SMR timer*/
    if (smr_timer == NULL){
        smr_timer = create_timer (SMR_TIMER);
    }
    start_timer(smr_timer, LISPD_SMR_TIMEOUT,(timer_callback)init_smr, NULL);

}