/* Check if binding has been used recently and send a binding refresh
 * request to get a new BU
 */
void mh_send_brr(struct in6_addr *mn_addr, struct in6_addr *local)
{
	struct iovec mh_vec;
	struct in6_addr_bundle addrs;
	struct timespec now;
	long last_used;

	clock_gettime(CLOCK_REALTIME, &now);

	last_used = xfrm_last_used(mn_addr, local, IPPROTO_ROUTING, &now);
	if (last_used < 0)
		return;
	if (last_used > CN_BRR_TIME_THRESH) {
		dbg("Binding is about to expire, no need to send a BRR\n");
		return;
	}
	/* Should we check for a BUL entry here? */
	dbg("Binding is about to expire, sending a BRR\n");
	addrs.src = local;
	addrs.dst = mn_addr;
	addrs.remote_coa = NULL;
	addrs.local_coa = NULL;

	if (!mh_create(&mh_vec, IP6_MH_TYPE_BRR))
		return;

	mh_send(&addrs, &mh_vec, 1, NULL, 0);
	free_iov_data(&mh_vec, 1);
}
void mh_send_ba(const struct in6_addr_bundle *addrs, uint8_t status,
		uint8_t flags, uint16_t sequence,
		const struct timespec *lifetime, const uint8_t *key, int iif)
{
	int iovlen = 1;
	struct ip6_mh_binding_ack *ba;
	struct iovec mh_vec[2];

	MDBG("status %d\n", status);

	ba = mh_create(mh_vec, IP6_MH_TYPE_BACK);
	if (!ba)
		return;

	ba->ip6mhba_status = status;
	ba->ip6mhba_flags = flags;
	ba->ip6mhba_seqno = htons(sequence);
	ba->ip6mhba_lifetime = htons(lifetime->tv_sec >> 2);

	if (status < IP6_MH_BAS_UNSPECIFIED && !conf.NonVolatileBindingCache) {
		struct timespec refresh;
		tsclear(refresh);
		if (conf.pmgr.use_bradv(addrs->dst, addrs->bind_coa,
					addrs->src, lifetime, &refresh) &&
		    tsbefore(*lifetime, refresh))
			mh_create_opt_refresh_advice(&mh_vec[iovlen++],
						     refresh.tv_sec);
	}
	if (key)
		mh_create_opt_auth_data(&mh_vec[iovlen++]);
	mh_send(addrs, mh_vec, iovlen, key, iif);
	free_iov_data(mh_vec, iovlen);
}
void mh_send_be(struct in6_addr *dst, struct in6_addr *hoa,
		struct in6_addr *src, uint8_t status, int iif)
{
	struct ip6_mh_binding_error *be;
	struct iovec iov;
	struct in6_addr_bundle out;

	if (IN6_IS_ADDR_UNSPECIFIED(dst) ||
	    IN6_IS_ADDR_LOOPBACK(dst) ||
	    IN6_IS_ADDR_MULTICAST(dst)) {
		MDBG("Omit BE for non-unicast "
		     "%x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(dst));
		return;
	}

	out.remote_coa = NULL;
	out.local_coa = NULL;
	be = mh_create(&iov, IP6_MH_TYPE_BERROR);
	if (!be)
		return;
	be->ip6mhbe_status = status;
	out.src = src;
	out.dst = dst;
	if (hoa)
		be->ip6mhbe_homeaddr = *hoa;
	out.dst = dst;

	mh_send(&out, &iov, 1, NULL, iif);
	free_iov_data(&iov, 1);
}
//---------------------------------------------------------------------------------------------------------------------
static int pmip_cache_delete_each(void *data, void *arg)
//---------------------------------------------------------------------------------------------------------------------
{
    pmip_entry_t *bce = (pmip_entry_t *) data;
    if (is_mag()) {
        //Delete existing route & rule for the deleted MN
        mag_remove_route(&bce->mn_addr, bce->link);
        int usercount = tunnel_getusers(bce->tunnel);
        dbg("# of binding entries %d \n", usercount);
        if (usercount == 1) {
            route_del(bce->tunnel, RT6_TABLE_PMIP, IP6_RT_PRIO_MIP6_FWD, &in6addr_any, 0, &in6addr_any, 0, NULL);
        }
        //decrement users of old tunnel.
        pmip_tunnel_del(bce->tunnel);
    }
    //Delete existing route for the deleted MN
    if (is_lma()) {
        lma_remove_route(&bce->mn_addr, bce->tunnel);
        //decrement users of old tunnel.
        pmip_tunnel_del(bce->tunnel);
    }
    //Delete the Entry.
    free_iov_data((struct iovec *) &bce->mh_vec, bce->iovlen);
    pmip_bce_delete(bce);
    return 0;
}
示例#5
0
//---------------------------------------------------------------------------------------------------------------------
void pmip_timer_retrans_pbu_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) {
            free_iov_data((struct iovec *) &e->mh_vec, e->iovlen);
            dbg("No PBA received from LMA....\n");
            dbg("Abort Trasmitting the PBU....\n");
            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));
            }
            pmip_bce_delete(e);
        } else {
            //Decrement the N trasnmissions counter.
            e->n_rets_counter--;
            struct in6_addr_bundle addrs;
            addrs.src = &conf.OurAddress;
            addrs.dst = &conf.LmaAddress;
            //sends a PBU
            dbg("Send PBU again....\n");

            // INCREMENT SEQ NUMBER OF PBU
            e->seqno_out        = get_new_pbu_sequence_number();
            ((struct ip6_mh_binding_update *)(e->mh_vec[0].iov_base))->ip6mhbu_seqno = htons(e->seqno_out);

            pmip_mh_send(&addrs, e->mh_vec, e->iovlen, e->link);
            //add a new task for PBU retransmission.
            struct timespec expires;
            clock_gettime(CLOCK_REALTIME, &e->add_time);
            tsadd(e->add_time, conf.RetransmissionTimeOut, expires);
            add_task_abs(&expires, &e->tqe, pmip_timer_retrans_pbu_handler);
            dbg("PBU Retransmissions timer is triggered again....\n");
            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));
            }
        }
    }
    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));
    }
}
int ndisc_send_na(int ifindex, const struct in6_addr *src,
                  const struct in6_addr *dst,
                  const struct in6_addr *target, uint32_t flags)
{
  struct nd_neighbor_advert *na;
  struct iovec iov[2];
  uint8_t l2addr[L2ADDR_MAX_SIZE];
  int len, iovlen = 0;

  memset(iov, 0, sizeof(iov));

  if ((len = ndisc_l2addr_to_opt(ifindex, l2addr)) < 0)
    return -EINVAL;

  na = icmp6_create(iov, ND_NEIGHBOR_ADVERT, iovlen++);

  if (na == NULL)
    return -ENOMEM;

  if (len > 0) {
    if (nd_opt_create(&iov[iovlen], ND_OPT_TARGET_LINKADDR,
                      len, l2addr) == NULL) {
      free_iov_data(iov, iovlen);
      return -ENOMEM;
    }

    iovlen++;
  }

  na->nd_na_target = *target;
  na->nd_na_flags_reserved = flags;

  icmp6_send(ifindex, 255, src, dst, iov, iovlen);
  free_iov_data(iov, iovlen);
  statistics_inc(&mipl_stat, MIPL_STATISTICS_OUT_NA);
  return 0;
}
示例#7
0
//---------------------------------------------------------------------------------------------------------------------
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));
    }
}