Beispiel #1
0
int ndisc_do_dad(int ifi, struct in6_addr *addr, int do_ll)
{
	struct in6_pktinfo pinfo;
	struct sockaddr_in6 saddr;
	struct nd_neighbor_advert *hdr;
	struct icmp6_filter filter;
	struct in6_addr solicit, ll;
	unsigned char msg[MAX_PKT_LEN];
	int hoplimit, sock = -1, ret, val = 1, err = -1;
	fd_set rset;
	struct timeval tv;

	ICMP6_FILTER_SETBLOCKALL(&filter);
	ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter);

	sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
	if (sock < 0) {
		dbg("socket: %s\n", strerror(errno));
		goto end;
	}

	if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
		       &val, sizeof(val)) < 0) {
		dbg("cannot set IPV6_RECVPKTINFO: %s\n", strerror(errno));
		goto end;
	}
	if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
		       &val, sizeof(val)) < 0) {
		dbg("cannot set IPV6_RECVHOPLIMIT: %s\n", strerror(errno));
		goto end;
	}
	if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
		       sizeof(struct icmp6_filter)) < 0) {
		dbg("cannot set ICMPV6_FILTER: %s\n", strerror(errno));
		goto end;
	}

	ipv6_addr_solict_mult(addr, &solicit);
	if (if_mc_group(sock, ifi, &in6addr_all_nodes_mc, IPV6_JOIN_GROUP)) {
		dbg("cannot join all node mc\n");
		goto end;
	}
	if (if_mc_group(sock, ifi, &solicit, IPV6_JOIN_GROUP)) {
		dbg("cannot joing slicit node mc\n");
		goto end;
	}
	if (ndisc_send_ns(ifi, addr) <= 0) {
		dbg("Error at sending NS\n");
		goto end;
	}

	if (do_ll) {
		ipv6_addr_llocal(addr, &ll);
		if (ndisc_send_ns(ifi, &ll) <= 0) {
			dbg("Error at sending NS (link-local target)\n");
			goto end;
		}
	}

	FD_ZERO(&rset);
	FD_SET(sock, &rset);
	tv.tv_sec = DAD_TIMEOUT;
	tv.tv_usec = 0;
	for (;;) {
		/* Note on portability: we assume that tv is modified to show
		   the time left which is AFAIK true only in Linux 
		   timeout 
		*/
		if (select(sock+1, &rset, NULL, NULL, &tv) == 0) {
			dbg("Dad success\n");
			err = 0;
			break;
		}
		if (!FD_ISSET(sock, &rset))
			continue;
		/* We got an ICMPv6 packet */
		ret = icmp6_recv(sock, msg, sizeof(msg), &saddr, 
				 &pinfo, &hoplimit);
		if (ret < 0)
			continue;
		hdr = (struct nd_neighbor_advert *)msg;
		if (hdr->nd_na_code != 0)
			continue;
		if (IN6_ARE_ADDR_EQUAL(addr, &hdr->nd_na_target) ||
		    (do_ll && IN6_ARE_ADDR_EQUAL(&ll, &hdr->nd_na_target))) {
			dbg("Failure\n");
			break;
		}
	}
 end:
	if (sock >= 0)
		close(sock);
	return err;
}
//---------------------------------------------------------------------------------------------------------------------
void pmip_timer_bce_expired_handler(struct tq_elem *tqe)
{
    int mutex_return_code;
    mutex_return_code = pthread_rwlock_wrlock(&pmip_lock);
    if (mutex_return_code != 0) {
        dbg("pthread_rwlock_wrlock(&pmip_lock) %s\n", strerror(mutex_return_code));
    }
    printf("-------------------------------------\n");
    if (!task_interrupted()) {
        pmip_entry_t *e = tq_data(tqe, pmip_entry_t, tqe);
        mutex_return_code = pthread_rwlock_wrlock(&e->lock);
        if (mutex_return_code != 0) {
            dbg("pthread_rwlock_wrlock(&e->lock) %s\n", strerror(mutex_return_code));
        }
        dbg("Retransmissions counter : %d\n", e->n_rets_counter);
        if (e->n_rets_counter == 0) {
            dbg("Retransmissions counter expired\n");
            free_iov_data((struct iovec *) &e->mh_vec, e->iovlen);
            if (is_mag()) {
                //++e->seqno_out;
                dbg("Calling deregistration\n");
                mag_dereg(e, 1);
                pmipcache_release_entry(e);
                pmip_bce_delete(e);
                return;
            }
            //Delete existing route for the deleted MN
            if (is_ha()) {
                lma_dereg(e, 0, 0);
                pmipcache_release_entry(e);
                pmip_bce_delete(e);
                return;
            }
            mutex_return_code = pthread_rwlock_unlock(&pmip_lock);
            if (mutex_return_code != 0) {
                dbg("pthread_rwlock_unlock(&pmip_lock) %s\n", strerror(mutex_return_code));
            }
            return;
        }
        if (is_mag()) {
            dbg("Send NS for Neighbour Reachability for:%x:%x:%x:%x:%x:%x:%x:%x iif=%d\n", NIP6ADDR(&e->mn_hw_address), e->link);
            //Create NS for Reachability test!
            //ndisc_send_ns(e->link, &conf.MagAddressIngress[0], solicited_mcast(&e->mn_suffix), get_mn_addr(e));
            ndisc_send_ns(e->link, get_mn_addr(e));


            struct timespec expires;
            clock_gettime(CLOCK_REALTIME, &e->add_time);
            tsadd(e->add_time, conf.RetransmissionTimeOut, expires);
            // Add a new task for deletion of entry if No Na is received.
            add_task_abs(&expires, &e->tqe, pmip_timer_bce_expired_handler);
            dbg("Start the Timer for Retransmission/Deletion ....\n");
            //Decrements the Retransmissions counter.
            e->n_rets_counter--;
            mutex_return_code = pthread_rwlock_unlock(&e->lock);
            if (mutex_return_code != 0) {
                dbg("pthread_rwlock_unlock(&e->lock) %s\n", strerror(mutex_return_code));
            }
        }
        if (is_ha()) {
            lma_dereg(e, 0, 0);
            pmipcache_release_entry(e);
            pmip_bce_delete(e);
            return;
        }
    }
    mutex_return_code = pthread_rwlock_unlock(&pmip_lock);
    if (mutex_return_code != 0) {
        dbg("pthread_rwlock_unlock(&pmip_lock) %s\n", strerror(mutex_return_code));
    }
}