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)); } }