//-----------------------------------------------------------------------------
struct in6_addr lma_mnid_hnp_map(struct in6_addr mnid, int *result)
{
  int j = 0;
  dbg("Entering the address match . . ");
  dbg("Searching for MNID  %x:%x:%x:%x:%x:%x:%x:%x  \n", NIP6ADDR(&mnid));

  while (j < g_mn_count) {
    dbg("Comparing with MNID  %x:%x:%x:%x:%x:%x:%x:%x  \n", NIP6ADDR(&g_mn_hn_map[j].mn_iid));

    if (IN6_ARE_ADDR_EQUAL(&g_mn_hn_map[j].mn_iid, &mnid)) {
      *result = 1;
      dbg("%x:%x:%x:%x:%x:%x:%x:%x found the prefix \n", NIP6ADDR(&g_mn_hn_map[j].mn_prefix));
      return (g_mn_hn_map[j].mn_prefix);
    }

    j++;
  }

  dbg("mnid not found ");

  struct in6_addr tmp;
  memset(&tmp, 0, sizeof(struct in6_addr));
  *result = -1;
  return tmp;
}
//---------------------------------------------------------------------------------------------------------------------
pmip_entry_t *pmip_cache_get(const  ip6mn_nai_t *mn_nai, const struct in6_addr *mag_addr)
{
    pmip_entry_t *bce;
    int mutex_return_code;

    assert(mn_nai && mag_addr);
    mutex_return_code = pthread_rwlock_rdlock(&pmip_lock);
    if (mutex_return_code != 0) {
        dbg("pthread_rwlock_rdlock(&pmip_lock) %s\n", strerror(mutex_return_code));
    }
    bce = pmip_hash_get(&g_pmip_hash, mn_nai, mag_addr);
    if (bce) {
        mutex_return_code = pthread_rwlock_wrlock(&bce->lock);
        if (mutex_return_code != 0) {
            dbg("pthread_rwlock_wrlock(&bce->lock) %s\n", strerror(mutex_return_code));
        }
        dbg("PMIP cache entry is found for: %x:%x:%x:%x:%x:%x:%x:%x with type %d\n", NIP6ADDR(&bce->mn_hw_address), (bce->type));
    } else {
        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));
        }

        dbg("PMIP cache entry is NOT found for %x:%x:%x:%x:%x:%x:%x:%x\n",  NIP6ADDR(mag_addr));
    }
    return bce;
}
Beispiel #3
0
void dump_bce(void *bce, void *os)
{
    struct bcentry *e = (struct bcentry *)bce;
    FILE *out = (FILE *)os;

    fprintf(out, " == Binding Cache entry ");

    switch(e->type) {
    case BCE_NONCE_BLOCK:
        fprintf(out, "(NONCE_BLOCK)\n");
        break;
    case BCE_CACHED:
        fprintf(out, "(CACHED)\n");
        break;
    case BCE_HOMEREG:
        fprintf(out, "(HOMEREG)\n");
        break;
    default:
        fprintf(out, "(Unknown)\n");
    }
    fprintf(out, " Care-of address %x:%x:%x:%x:%x:%x:%x:%x\n",
            NIP6ADDR(&e->coa));
    fprintf(out, " Home address    %x:%x:%x:%x:%x:%x:%x:%x\n",
            NIP6ADDR(&e->peer_addr));
    fprintf(out, " Local address   %x:%x:%x:%x:%x:%x:%x:%x\n",
            NIP6ADDR(&e->our_addr));
    fprintf(out, " lifetime %ld\n ", e->lifetime.tv_sec);
    fprintf(out, " seqno %d\n", e->seqno);

    fflush(out);
}
Beispiel #4
0
void dump_bule(void *bule, void *os)
{
	struct bulentry *e = (struct bulentry *)bule;
	FILE *out = (FILE *)os;

	if (e->type == BUL_ENTRY)
		fprintf(out, "== BUL_ENTRY ==\n");
	else if (e->type == NON_MIP_CN_ENTRY)
		fprintf(out, "== NON_MIP_CN_ENTRY ==\n");
	else if (e->type == UNREACH_ENTRY)
		fprintf(out, "== UNREACH_ENTRY ==\n");
	else 
		fprintf(out, "== Unknown BUL entry ==\n");

	fprintf(out, "Home address    %x:%x:%x:%x:%x:%x:%x:%x\n",
		NIP6ADDR(&e->hoa));
	fprintf(out, "Care-of address %x:%x:%x:%x:%x:%x:%x:%x\n",
		NIP6ADDR(&e->coa));
	fprintf(out, "CN address      %x:%x:%x:%x:%x:%x:%x:%x\n",
		NIP6ADDR(&e->peer_addr));
	fprintf(out, " lifetime = %ld, ", e->lifetime.tv_sec);
	fprintf(out, " delay = %ld\n", tstomsec(e->delay));
	fprintf(out, " flags: ");
	if (e->flags & IP6_MH_BU_HOME)
		fprintf(out, "IP6_MH_BU_HOME ");
	if (e->flags & IP6_MH_BU_ACK)
		fprintf(out, "IP6_MH_BU_ACK ");
	if (e->flags & IP6_MH_BU_LLOCAL)
		fprintf(out, "IP6_MH_BU_LLOCAL");
	if (e->flags & IP6_MH_BU_KEYM)
		fprintf(out, "IP6_MH_BU_KEYM");

	fprintf(out, "\n");
	fflush(out);
}
//---------------------------------------------------------------------------------------------------------------------
int pmip_mag_init(void)
//---------------------------------------------------------------------------------------------------------------------
{
	pmip_common_init();
	conf.OurAddress = conf.MagAddressEgress;
	conf.HomeNetworkPrefix = get_node_prefix(&conf.MagAddressIngress); //copy Home network prefix.
	dbg("Running as MAG entity\n");
	dbg("Entity Egress Address: %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&conf.OurAddress));
	dbg("Entity Ingress Address: %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&conf.MagAddressIngress));
	dbg("Home Network Prefix Address: %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&conf.HomeNetworkPrefix));
	if (mag_init_fsm() < 0) {
		dbg("Initialization of FSM failed...exit\n");
		exit(-1);
	}
	init_iface_ra();
	init_mag_icmp_sock();
	dbg("Initializing the NA handler\n");
	// to capture NA message
	icmp6_handler_reg(ND_NEIGHBOR_ADVERT, &pmip_mag_recv_na_handler);
	dbg("Initializing the RS handler\n");
	// to capture RS message
	icmp6_handler_reg(ND_ROUTER_SOLICIT, &pmip_mag_rs_handler);
	dbg("Initializing the PBA handler\n");
	//To capture PBA/ message.
	mh_handler_reg(IP6_MH_TYPE_BACK, &pmip_mag_pba_handler);
	//Anh Khuong: handle RO messages
	mh_handler_reg(IP6_MH_TYPE_ROI, &pmip_mag_roi_handler);
	mh_handler_reg(IP6_MH_TYPE_ROS, &pmip_mag_ros_handler);
	mh_handler_reg(IP6_MH_TYPE_ROSA, &pmip_mag_rosa_handler);
	mh_handler_reg(IP6_MH_TYPE_ETM, &pmip_mag_etm_handler);
	mh_handler_reg(IP6_MH_TYPE_HI, &pmip_mag_hi_handler);
	mh_handler_reg(IP6_MH_TYPE_HA, &pmip_mag_ha_handler);
	/**
	* Deletes the default route for MN prefix so routing is per unicast MN address!
	**/
	route_del((int) NULL, RT6_TABLE_MAIN, IP6_RT_PRIO_ADDRCONF, &in6addr_any, 0, &conf.HomeNetworkPrefix, 64, NULL);
	dbg("Initializing the HNP cache\n");
	if (pmip_mn_to_hnp_cache_init() < 0) {
		exit (-1);
	}

    char devname[32];
	int iif;
	dbg("Getting ingress informations\n");
	mag_get_ingress_info(&iif, devname);
	dbg("Starting capturing AP messages for incoming MNs detection\n");
	pmip_pcap_loop(devname, iif);

	return 0;
}
Beispiel #6
0
//---------------------------------------------------------------------------
// Find the IP traffic type (UNICAST, MULTICAST, BROADCAST)
ip_traffic_type_t oai_nw_drv_find_traffic_type(struct sk_buff  *skb)
{
  //---------------------------------------------------------------------------
  ip_traffic_type_t            traffic_type = TRAFFIC_IPVX_TYPE_UNKNOWN;

  if (skb!=NULL) {
    switch (ntohs(skb->protocol))  {
    case ETH_P_IPV6:
      traffic_type = TRAFFIC_IPV6_TYPE_UNKNOWN;
#ifdef OAI_DRV_DEBUG_CLASS
      printk("SOURCE ADDR %X:%X:%X:%X:%X:%X:%X:%X",NIP6ADDR(&(ipv6_hdr(skb)->saddr)));
      printk("    DEST   ADDR %X:%X:%X:%X:%X:%X:%X:%X\n",NIP6ADDR(&(ipv6_hdr(skb)->daddr)));
#endif

      if (IN6_IS_ADDR_MULTICAST(&ipv6_hdr(skb)->daddr.in6_u.u6_addr32[0])) {
        traffic_type = TRAFFIC_IPV6_TYPE_MULTICAST;

      } else {
        traffic_type = TRAFFIC_IPV6_TYPE_UNICAST;
      }

      break;


    case ETH_P_IP:
      traffic_type = TRAFFIC_IPV4_TYPE_UNKNOWN;

      //print_TOOL_pk_ipv4((struct iphdr *)skb->network_header);
      if (IN_MULTICAST(htonl(ip_hdr(skb)->daddr))) {
        traffic_type = TRAFFIC_IPV4_TYPE_MULTICAST;
      } else {
        traffic_type = TRAFFIC_IPV4_TYPE_UNICAST;
      }

      // TO DO BROADCAST

      break;

    case ETH_P_ARP:
      traffic_type = TRAFFIC_IPV4_TYPE_BROADCAST;
      break;

    default:
      ;
    }
  }

  return traffic_type;
}
//---------------------------------------------------------------------------------------------------------------------
int pmip_lma_init(void)
//---------------------------------------------------------------------------------------------------------------------
{
	pmip_common_init();
	pmip_lma_mn_to_hnp_cache_init();
	conf.OurAddress = conf.LmaAddress;
	dbg("Entity Address: %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&conf.OurAddress));
	dbg("Initializing the PBU handler\n");
	//To capture PBU message.ss
	mh_handler_reg(IP6_MH_TYPE_BU, &pmip_lma_pbu_handler);
	//Anh Khuong: handle RO messages
	mh_handler_reg(IP6_MH_TYPE_ROT, &pmip_lma_rot_handler);

#ifdef LMA_BUFFERING
	dbg("Initializing the buffering module\n");
	if (pmip_buffering_init() < 0) {
		pmip_buffering_cleanup();
		return -1;
	}
#endif

	undefined_RO = 0;
#ifdef USE_PMIP_RO
	if (pmip_ro_init() < 0) {
		undefined_RO = 1;
		dbg("LMA couldn't support RO because there is no RO module installed under network layer\n");
	}
	else { // update policy
		pmip_ro_setup_policy();
	}
#endif
	return 0;
}
//---------------------------------------------------------------------------------------------------------------------
pmip_entry_t *pmip_cache_add(pmip_entry_t * bce)
{
    int ret = 1;
    int mutex_return_code;
    assert(bce);
    bce->unreach = 0;
    mutex_return_code = pthread_rwlock_wrlock(&pmip_lock);
    last_BID++;
    bce->BID=last_BID;

    if (mutex_return_code != 0) {
        dbg("pthread_rwlock_wrlock(&pmip_lock) %s\n", strerror(mutex_return_code));
    }
    if ((ret = __pmipcache_insert(bce)) != 0) {
        pthread_rwlock_unlock(&pmip_lock);
        dbg("WARNING: PMIP ENTRY NOT INSERTED..\n");
        return NULL;
    }
    dbg("Making Entry\n");
    dbg("PMIP cache entry for: %x:%x:%x:%x:%x:%x:%x:%x with type %d is added\n", NIP6ADDR(&bce->mn_hw_address), bce->type);
    bce->n_rets_counter = conf.MaxMessageRetransmissions;
    dbg("Retransmissions counter intialized: %d\n", bce->n_rets_counter);
    if (bce->type == BCE_PMIP) {
        pmip_cache_start(bce);
    }
    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 bce;
}
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);
}
int pmip_mn_to_hnp_cache_init (void)
{
  FILE               *fp;

  char                line [256];
  char                str_addr[40], str_addr_iid[40];

  struct in6_addr     addr, addr1;

  unsigned int        ap, ap1;

  int                 i, j;

  memset(g_mn_hn_map, 0, sizeof(mnid_hnp_t) * MAX_MOBILES);
  j = 0;

  if ((fp = fopen ("/etc/pmip/mac-mapping.auth", "r")) == NULL) {
    printf ("can't open %s:", "/etc/pmip/mac-mapping.auth");
    exit (0);
  }

  while ( fgets ( line, sizeof line, fp ) != NULL ) {
    trim(line);

    // if line is not a comment
    if (strncmp("#", line, 1) != 0) {
      //while ((fscanf (fp, "%32s %16s\n", str_addr, str_addr_iid) != EOF) && (j < MAX_MOBILES)) {
      if ((sscanf (line, "%32s %16s\n", str_addr, str_addr_iid) != EOF) && (j < MAX_MOBILES)) {
        for (i = 0; i < 16; i++) {
          sscanf (str_addr + i * 2, "%02x", &ap);
          addr.s6_addr[i] = (unsigned char) ap;
          g_mn_hn_map[j].mn_prefix = addr;

          addr1.s6_addr[i] = 0;
        }

        for (i = 0; i < 8; i++) {
          sscanf (str_addr_iid + i * 2, "%02x", &ap1);
          addr1.s6_addr[i+8] = (unsigned char) ap1;
          g_mn_hn_map[j].mn_iid = addr1;
        }

        dbg ("%x:%x:%x:%x:%x:%x:%x:%x\t<->\t%x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR (&g_mn_hn_map[j].mn_prefix), NIP6ADDR (&g_mn_hn_map[j].mn_iid));
        j++;
        g_mn_count = g_mn_count + 1;
      }
    }
  }

  fclose (fp);

  if (j >= MAX_MOBILES) {
    dbg ("ERROR TOO MANY MAPPINGS DEFINED IN CONFIG FILE\n");
    exit (0);
  }

  return 0;
}
//---------------------------------------------------------------------------------------------------------------------
void dump_pbce(void *bce, void *os)
{
	pmip_entry_t *e = (pmip_entry_t *) bce;
	FILE *out = (FILE *) os;
	fprintf(out, " == Proxy Binding Cache entry ");
	switch (e->type) {
		case BCE_PMIP:
			fprintf(out, "(BCE_PMIP)\n");
			break;
		case BCE_TEMP:
			fprintf(out, "(BCE_TEMP)\n");
			break;
		default:
			fprintf(out, "(Unknown)\n");
	}
	fprintf(out, " MN IID:                 %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&e->mn_suffix));
	fprintf(out, " MN HW Address:          %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&e->mn_hw_address));
	fprintf(out, " MN Serving MAG Address: %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&e->mn_serv_mag_addr));
	fprintf(out, " MN Serving LMA Address: %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&e->mn_serv_lma_addr));
	fprintf(out, " lifetime %ld\n ", e->lifetime.tv_sec);
	fprintf(out, " seqno    %d\n", e->seqno_out);
	fflush(out);
}
//-----------------------------------------------------------------------------
void pmip_insert_into_hnp_cache(struct in6_addr mn_iid, struct in6_addr addr)
{
  int j = 0;

  while (j < g_mn_count) {
    if (IN6_ARE_ADDR_EQUAL(&g_mn_hn_map[j].mn_iid, &mn_iid)) {
      dbg("mnid %x:%x:%x:%x:%x:%x:%x:%x already in cache, updating addr %x:%x:%x:%x:%x:%x:%x:%x -> %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&g_mn_hn_map[j].mn_iid), NIP6ADDR(&g_mn_hn_map[j].mn_prefix),
          NIP6ADDR(&addr));
      g_mn_hn_map[j].mn_prefix = addr;
      return;
    }

    j++;
  }

  if (g_mn_count < MAX_MOBILES) {
    g_mn_hn_map[g_mn_count].mn_prefix = addr;
    g_mn_hn_map[g_mn_count].mn_iid = mn_iid;
    dbg("new entry in cache %x:%x:%x:%x:%x:%x:%x:%x -> %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&g_mn_hn_map[g_mn_count].mn_prefix), NIP6ADDR(&g_mn_hn_map[g_mn_count].mn_iid));
    g_mn_count = g_mn_count + 1;
  } else {
    dbg("ERROR COULD NOT PUT NEW ENTRY IN CACHE %x:%x:%x:%x:%x:%x:%x:%x -> %x:%x:%x:%x:%x:%x:%x:%x MAX ENTRIES REACHED\n", NIP6ADDR(&addr), NIP6ADDR(&mn_iid));
  }
}
//---------------------------------------------------------------------------------------------------------------------
static int __pmipcache_insert(pmip_entry_t * bce)
{
    int ret;
    ret = pmip_hash_add(&g_pmip_hash, bce, &bce->mn_nai, &bce->mn_serv_mag_addr);
    if (ret) {
        return ret;
    }
    g_pmip_cache_count++;

    dbg("PMIP cache entry is inserted for: ");
    dbg_buf_string(&bce->mn_nai.nai, sizeof(ip6mn_nai_t));
    dbg(" <=> %x:%x:%x:%x:%x:%x:%x:%x\n",  NIP6ADDR(&bce->mn_serv_mag_addr));

    return 0;
}
//---------------------------------------------------------------------------------------------------------------------
int pmip_cache_exists(const  ip6mn_nai_t *mn_nai, const struct in6_addr *mag_addr)
{
    pmip_entry_t *bce;
    int type;
    bce = pmip_cache_get(mn_nai, mag_addr);
    if (bce == NULL) {
        dbg("PMIP cache wasn't found for: ");
        dbg_buf_string(&mn_nai->nai, sizeof(ip6mn_nai_t));
        dbg(" <=> %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(mag_addr));
        return -1;
    }
    dbg("PMIP cache entry does exist with type: %d\n", (bce->type));
    type = bce->type;
    pmipcache_release_entry(bce);
    return type;
}
Beispiel #15
0
int icmp6_parse_data(struct ip6_hdr *ip6h, unsigned int len, 
		     struct in6_addr **lhoa, struct in6_addr **rhoa)
{
	uint8_t *data = (uint8_t *)ip6h;
	unsigned int hoff = sizeof(struct ip6_hdr);
	uint8_t htype;

	if (len < hoff)
		return -1;

	htype = ip6h->ip6_nxt;

	/* The minumum length of an extension header is eight octets,
	   so check that we at least have room for that */
	while (hoff + 8 < len) {
		struct ip6_ext *h = (struct ip6_ext *) (data + hoff);
		unsigned int hlen = (h->ip6e_len + 1) << 3;

		if (htype != IPPROTO_DSTOPTS && 
		    htype != IPPROTO_ROUTING &&
		    htype != IPPROTO_HOPOPTS)
			return 0;

		if (len < hoff + hlen)
			return -1;

		if (htype == IPPROTO_DSTOPTS) {
			uint8_t *odata = (uint8_t *) h;
			uint32_t ooff = 2;
			while (ooff < hlen) {
				struct ip6_subopt_hdr *o;
				o = (struct ip6_subopt_hdr *) (odata + ooff);
				if (o->opttype == IP6OPT_PAD0) {
					ooff++;
					continue;
				}
				/* invalid TLV option length */
				if (hlen < ooff + 2 ||
				    hlen < ooff + 2 + o->optlen)
					break;
				if (o->opttype == IP6OPT_HOME_ADDRESS &&
				    o->optlen == sizeof(struct in6_addr)) {
					*lhoa = (struct in6_addr *) (o + 1);
					dbg("HAO %x:%x:%x:%x:%x:%x:%x:%x\n",
					    NIP6ADDR(*lhoa));
					break;
				}
				ooff += 2 + o->optlen;
			}
		} else if (htype == IPPROTO_ROUTING) {
			struct ip6_rthdr2 *rth = (struct ip6_rthdr2 *) h;
			if (rth->ip6r2_type == 2 && 
			rth->ip6r2_len == 2 && rth->ip6r2_segleft == 1)
				*rhoa = &rth->ip6r2_homeaddr;
			dbg("RTH2 %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(*rhoa));
		} else if (htype != IPPROTO_HOPOPTS) {
			return 0;
		}
		hoff += hlen;
		htype = h->ip6e_nxt;
	}
	return 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));
    }
}
Beispiel #17
0
//---------------------------------------------------------------------------------------------------------------------
void mar_fsm(msg_info_t * info)
{
	int aaa_result = 0;
	dmm_entry *bce = NULL;
	struct in6_addr *prefix;
	struct in6_addr hw_address = EUI64_to_EUI48(info->mn_iid);
	int mutex_return_code;

	mutex_return_code = pthread_rwlock_wrlock(&fsm_lock);
	if (mutex_return_code != 0) {
		dbg("pthread_rwlock_wrlock(&fsm_lock) %s\n", strerror(mutex_return_code));
	}
	//dbg("Entered FSM\n");
	bce = dmm_cache_get(&conf.OurAddress, &hw_address);
	switch (info->msg_event) {
	//--------------------------------------
	case hasRS:
		if (!bce) {
			dbg("New MN is found sending RS, checking AAA ...\n");
			prefix = mnid_hnp_map(&hw_address);
			if (prefix) {
				//dbg("AAA success: prefix to assign: %x:%x:%x:%x:%x:%x:%x:%x \n", NIP6ADDR(prefix));
				memcpy(&info->mn_prefix, prefix, sizeof(struct in6_addr));
				/* allocate memory for BCE */
				bce = dmm_cache_alloc(BCE_TEMP);
				if (bce) {				
					/* Fill BCE with MN's parameters */
					mar_create_binding_entry(info, bce);
					/* Send PBU to CMD for registration */
					mar_start_registration(bce);
					dmm_cache_add(bce);
					dbg("BCE registered\n");
				} else {
					dbg("Problems creating BCE\n");
					break;
				}
			} else {
				dbg("AAA failed\n");
			}
		} else {
			switch (bce->type) {
				case BCE_TEMP:
					dbg("BCE already existing but not finalized -> Request Rejected\n");
					dmm_cache_release(bce);
				break;
				case BCE_DMM:
					dbg("Router solicitation received for existing MN:\n");
					int update = mar_update_binding_entry(bce, info);
					if (update == 1) mar_start_registration(bce);
					else {
						mar_force_update_registration(bce, info);
					}
					dmm_cache_release(bce);
					break;
				default:
					dbg("No action for this event (%d) at current state (%d) !\n", info->msg_event, bce->type);
					dmm_cache_release(bce);
				}
		}
	break;
		//--------------------------------------
	case hasPBA:
		if (!bce) {
			dbg("PBA received for not registered MN -> discarded\n");
			break;
		} else {
			switch (bce->type) {
			case BCE_TEMP:
				if (is_pba_is_response_to_last_pbu_sent(info, bce)) {
					dbg("Handling PBA. Moving from BCE_TEMP to BCE_DMM\n");
					
					del_task(&bce->tqe);    //Delete timer retransmission PBU (if any)
					bce->PBA_flags = info->PBA_flags;
					if (info->lifetime.tv_sec > 30) {
						bce->lifetime.tv_sec = info->lifetime.tv_sec - 8;
						dbg("Set BCE lifetime to PBA lifetime (%d seconds) - 8 second = %d seconds\n", info->lifetime.tv_sec, bce->lifetime.tv_sec);
					} else if (info->lifetime.tv_sec > 5) {
						bce->lifetime.tv_sec = info->lifetime.tv_sec - 3;
						dbg("Set BCE lifetime to PBA lifetime (%d seconds) - 3 second = %d seconds\n", info->lifetime.tv_sec, bce->lifetime.tv_sec);
					} else if (info->lifetime.tv_sec > 1) {
							bce->lifetime.tv_sec = info->lifetime.tv_sec - 1;
							dbg("Set BCE lifetime to PBA lifetime (%d seconds) - 1 second = %d seconds\n", info->lifetime.tv_sec, bce->lifetime.tv_sec);
					} else {
						bce->lifetime.tv_sec = info->lifetime.tv_sec;
						dbg("Set BCE lifetime to PBA lifetime (%d seconds) =  %d seconds\n", info->lifetime.tv_sec, bce->lifetime.tv_sec);
					}
					if (info->mn_p_mar_addr) {
						mar_list_clean(bce->mar_list);
						bce->mar_list = info->mn_p_mar_addr;
					}
					mar_end_registration(bce, info->iif);
				}
				dmm_cache_release(bce);
			break;
		//--------------------------------------
			case BCE_DMM:
				if (is_pba_is_response_to_last_pbu_sent(info, bce)) {
					del_task(&bce->tqe);    //Delete timer retransmission PBU (if any)
					bce->PBA_flags = info->PBA_flags;
					bce->lifetime.tv_nsec = 0;
					if (info->lifetime.tv_sec > 10) {
						bce->lifetime.tv_sec = info->lifetime.tv_sec - 8;
						dbg("Set BCE lifetime to PBA lifetime (%d seconds) - 8 second = %d seconds\n", info->lifetime.tv_sec, bce->lifetime.tv_sec);
					} else if (info->lifetime.tv_sec > 5) {
						bce->lifetime.tv_sec = info->lifetime.tv_sec - 3;
						dbg("Set BCE lifetime to PBA lifetime (%d seconds) - 3 second = %d seconds\n", info->lifetime.tv_sec, bce->lifetime.tv_sec);
					} else if (info->lifetime.tv_sec > 1) {
						bce->lifetime.tv_sec = info->lifetime.tv_sec - 1;
						dbg("Set BCE lifetime to PBA lifetime (%d seconds) - 1 second = %d seconds\n", info->lifetime.tv_sec, bce->lifetime.tv_sec);
					} else {
						bce->lifetime.tv_sec = info->lifetime.tv_sec;
						dbg("Set BCE lifetime to PBA lifetime (%d seconds) =  %d seconds\n", info->lifetime.tv_sec, bce->lifetime.tv_sec);
					}
					mar_end_registration_no_new_tunnel(bce, info->iif);
				}
				dmm_cache_release(bce);
			break;
			default:
				dbg("No action for this event (%d) at current state (%d) !\n", info->msg_event, bce->type);
				dmm_cache_release(bce);
			}
		}
	break;
	case hasNA:
		//Reset counter, Delete task for entry deletion  & Add a new task for NS expiry.
		if (!bce) {
			dbg("Received NA for a not registered MN -> reject\n");
			break;
		} else if (bce->type == BCE_DMM) {
			if (bce->n_rets_counter == conf.MaxMessageRetransmissions)
				dbg("Received NA for not expired BCE");
			else {
				bce->n_rets_counter = conf.MaxMessageRetransmissions;    //Reset the Retransmissions Counter.
				dbg("Reset the Reachability Counter = %d for %x:%x:%x:%x:%x:%x:%x:%x\n", bce->n_rets_counter, NIP6ADDR(&info->mn_iid));
				del_task(&bce->tqe);
				mar_force_update_registration(bce, info->iif);
			}
			dmm_cache_release(bce);
		} else {
			dbg("Cannot accept NA for not registered MN\n");
			dmm_cache_release(bce);
		}
	break;
	case hasPBU:
		if (!bce) {
			dbg("Received PBU for a not registered MN -> reject\n");
			break;
		} else if (bce->type == BCE_DMM) {
			/* 
			Install routes and tunnel for the MN
			Send a PBA to the CMD with the P-MAR option
			*/
			if (!IN6_ARE_ADDR_EQUAL(&conf.CmdAddress, &info->src)){
				dbg("Received PBU from a non-CMD node -> rejected\n");
				break;
			} else {
				if (info->lifetime.tv_sec > 0) {
					if (!IN6_IS_ADDR_UNSPECIFIED(&info->mn_serv_mar_addr)) {
						dbg("Stopping BCE timer, no longer needed\n");
						bce->mn_serv_mar_addr = info->mn_serv_mar_addr;
						bce->timestamp.first    = info->timestamp.first;
						bce->timestamp.second   = info->timestamp.second;
						mar_end_registration_dmm(bce, info->iif);
					} else
						dbg("ERROR: No Serving MAR found\n");
				} else if (info->lifetime.tv_sec == 0 && info->lifetime.tv_nsec == 0) {
					bce->seqno_in = info->seqno;
					mar_dereg_dmm(bce);
					dmm_cache_delete(bce);
				}
			}
			dmm_cache_release(bce);
		} else	{
			dbg("Cannot accept PBU for not registered MN\n");
			dmm_cache_release(bce);
		}
	break;
	default:
		dbg("No action for this event (%d) at current state !\n", info->msg_event);
	}
	mutex_return_code = pthread_rwlock_unlock(&fsm_lock);
	if (mutex_return_code != 0) {
		dbg("pthread_rwlock_unlock(&fsm_lock) %s\n", strerror(mutex_return_code));
	}
	dbg("exiting FSM - Waiting for new messages ...\n\n\n");
	return;
}
//---------------------------------------------------------------------------
// Search the entity with the IPv6 address 'addr'
// Navid: the ipv6 classifier is not fully tested
struct cx_entity *nasmt_CLASS_cx6(struct sk_buff *skb, unsigned char dscp, int *paddr_type, unsigned char *cx_index)
{
  //---------------------------------------------------------------------------
  uint8_t cxi;
  struct cx_entity *cx = NULL;
  struct classifier_entity *sclassifier= NULL;
  uint32_t mc_addr_hdr;
  struct in6_addr masked_addr;

#ifdef NAS_DEBUG_CLASS
  printk("nasmt_CLASS_cx6: begin\n");
#endif

  if (skb) {
#ifdef NAS_DEBUG_CLASS
    printk("SOURCE ADDR %X:%X:%X:%X:%X:%X:%X:%X",NIP6ADDR(&(ipv6_hdr(skb)->saddr)));
    printk(" DEST ADDR %X:%X:%X:%X:%X:%X:%X:%X\n",NIP6ADDR(&(ipv6_hdr(skb)->daddr)));
#endif
    mc_addr_hdr = ntohl(ipv6_hdr(skb)->daddr.in6_u.u6_addr32[0]);

    // First check if multicast [1st octet is FF]
    if ((mc_addr_hdr & 0xFF000000) == 0xFF000000) {
      // packet type according to the scope of the multicast packet
      // we don't consider RPT bits in second octet [maybe done later if needed]
      switch(mc_addr_hdr & 0x000F0000) {
      case (0x00020000):
        *paddr_type = NAS_IPV6_ADDR_MC_SIGNALLING;
#ifdef NAS_DEBUG_CLASS
        printk("nasmt_CLASS_cx6: multicast packet - signalling \n");
#endif
        break;

      default:
        printk("nasmt_CLASS_cx6: default multicast\n");
        *paddr_type = NAS_IPV6_ADDR_UNKNOWN;
      }
    } else {
      // This is not multicast, so we should be able to identify the MT
      *paddr_type = NAS_IPV6_ADDR_UNICAST;
      cxi = 0;
      (*cx_index)++;
      sclassifier = gpriv->cx[cxi].sclassifier[dscp];

      while (sclassifier!=NULL) {
        // verify that this is an IPv6 classifier
        if ((sclassifier->version == NAS_VERSION_6) || (sclassifier->version == NAS_VERSION_DEFAULT)) {
          /*LGif (IN6_IS_ADDR_UNSPECIFIED(&(sclassifier->daddr.ipv6))) {
            printk("nas_CLASS_cx6: addr is null \n");
            sclassifier = sclassifier->next;
            continue;
            }*/
#ifdef NAS_DEBUG_CLASS
          printk("cx %d : DSCP %d %X:%X:%X:%X:%X:%X:%X:%X\n",cxi, dscp, NIP6ADDR(&(sclassifier->daddr.ipv6)));
#endif //NAS_DEBUG_CLASS

          //if ((dst = (unsigned int*)&(((struct rt6_info *)skbdst)->rt6i_gateway)) == 0){
          // LG: STRANGE
          if (IN6_IS_ADDR_UNSPECIFIED(&ipv6_hdr(skb)->daddr)) {
            printk("nasmt_CLASS_cx6: dst addr is null \n");
            sclassifier = sclassifier->next;
            continue;
          }

          nasmt_create_mask_ipv6_addr(&masked_addr, sclassifier->dplen);
          // Modified MW to check only the iid6
          masked_addr.s6_addr32[0] = 0x00000000;
          masked_addr.s6_addr32[1] = 0x00000000;

          if (IN6_ARE_ADDR_MASKED_EQUAL(&ipv6_hdr(skb)->daddr, &(sclassifier->daddr.ipv6), &masked_addr)) {
#ifdef NAS_DEBUG_CLASS
            printk("nasmt_CLASS_cx6: found cx %d: %X:%X:%X:%X:%X:%X:%X:%X\n",cxi, NIP6ADDR(&(sclassifier->daddr.ipv6)));
#endif //NAS_DEBUG_CLASS
            return &gpriv->cx[cxi];
          }
        }

        // Go to next classifier entry for connection
        sclassifier = sclassifier->next;
      }
    }
  }

  //printk("nas_CLASS_cx6 NOT FOUND: %X:%X:%X:%X:%X:%X:%X:%X\n",NIP6ADDR(&ipv6_hdr(skb)->daddr));
  return cx;
}
void flowScheduler_link_up( ip6mn_nai_t mn_nai, struct in6_addr serving_mag){

    dbg("Link UP - Rescheduling all flows from client [PUT NAI HERE] passing in MAG %x:%x:%x:%x:%x:%x:%x:%x \n",NIP6ADDR(&serving_mag));

    flowmob_cache_iterate(flowScheduler_new_path, &mn_nai);

    dbg("Flows Rescheduled\n");
}
Beispiel #20
0
//---------------------------------------------------------------------------------------------------------------------
int cmd_fsm(msg_info_t * info)
{
	if (!info) {
		dbg("Input parameter fail: Cannot proceed\n");
		return -1;
	}
	int result = 0;
	dmm_entry *bce = NULL;
	struct in6_addr hw_address = EUI64_to_EUI48(info->mn_iid);
	
	bce = dmm_cache_get(&conf.OurAddress, &hw_address);
	switch (info->msg_event) {
	/*
	 * Two possible events:
	 * PBU reception;
	 * PBA reception.
	 * All other received messages are discarded
	 */
	case hasPBU:
		if (bce) {
			if (info->lifetime.tv_sec > 0) {
				if (IN6_ARE_ADDR_EQUAL(&bce->mn_serv_mar_addr, &info->src)) {
					dbg("Same serving MAR: %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&info->src));
					cmd_refresh_binding_entry(bce, info);
					cmd_reg(bce);
					dmm_cache_release(bce);
				} else {					
					dbg("PBU for an existing MN ... update serving MAR\n");
					cmd_update_binding_entry(bce, info);
					cmd_reg_dmm(bce);
					dmm_cache_release(bce);
				}
			} else if (info->lifetime.tv_sec == 0 && info->lifetime.tv_nsec == 0) {
				dbg("PBU with Lifetime = 0... start Location Deregistration\n");
				if (IN6_ARE_ADDR_EQUAL(&info->src, &bce->mn_serv_mar_addr)) //Received PBU from serving MAG
				{		
					dbg("Deregistration case...\n");
					cmd_dereg(bce, info, 1);
					dmm_cache_release(bce);
					dmm_cache_delete(bce);
				} else { //Received PBU from an already unregistered MAG
					dbg("Deregistration for not registered MAG, doing nothing\n");
					dmm_cache_release(bce);
					}
				}
		} else {
			dbg("No DMM entry found for %x:%x:%x:%x:%x:%x:%x:%x ... \n", NIP6ADDR(&info->mn_iid));
			if (info->lifetime.tv_sec > 0) {
				dbg("PBU for a new MN ... Location Registration starting now...\n");
				bce = dmm_cache_alloc(BCE_DMM);
				if (bce) {
					insert_into_hnp_cache(hw_address, info->mn_prefix);
					result = cmd_create_binding_entry(bce, info);
					if (result >= 0)
						cmd_reg(bce);
					else break;
				dmm_cache_add(bce);
				}
			} else if ((info->lifetime.tv_sec == 0) && (info->lifetime.tv_nsec == 0)) {
				dbg("PBU with Lifetime = 0 for a not-registered MN. PBU discarded\n");
				}
			}
	break;
	case hasPBA:
			if (bce) {
				dbg("Received PBA from Previous MAR: BCE updated\n");
				if (is_pba_is_response_to_last_pbu_sent(info, bce)) {
					dbg("Finish Location Registration\n");
					bce->PBA_flags = info->PBA_flags;
					bce->lifetime.tv_nsec = 0;
					if (!IN6_IS_ADDR_UNSPECIFIED(&info->mn_serv_mar_addr)) {
						cmd_end_reg_dmm(bce, &info->mn_prefix);
					}
				}
				dmm_cache_release(bce);
			} else {
				dbg("WARNING: Received PBA for a not registered MN\n");
			}
	break;
	default:
		dbg("No action for this event (%d) at current state!\n", info->msg_event);
	}
	return result;
}
/*!
*  Search if the mobile node id is already associated with a prefix in the hnp map
* \param mnid Mobile node ID
* \return a valid prefix if the mobile node id is already associated with a prefix in the hnp map
*/
struct in6_addr mnid_hnp_map(struct in6_addr mnid, int *aaa_result)
{
  int l_flag = 0;
#if !defined (USE_RADIUS) || defined(CACHE_RADIUS)
  int j = 0;
  dbg("Entering the address match . . \n");
  dbg("Searching for MNID  %x:%x:%x:%x:%x:%x:%x:%x  \n", NIP6ADDR(&mnid));

  while (j < g_mn_count) {
    dbg("Comparing with MNID  %x:%x:%x:%x:%x:%x:%x:%x  \n", NIP6ADDR(&g_mn_hn_map[j].mn_iid));

    if (IN6_ARE_ADDR_EQUAL(&g_mn_hn_map[j].mn_iid, &mnid)) {
      l_flag = 1;
      dbg("%x:%x:%x:%x:%x:%x:%x:%x found the prefix \n", NIP6ADDR(&g_mn_hn_map[j].mn_prefix));
      *aaa_result = 10;
      return (g_mn_hn_map[j].mn_prefix);
    }

    j++;
  }

#ifdef CACHE_RADIUS
  dbg("MNID not in cache  %x:%x:%x:%x:%x:%x:%x:%x  \n", NIP6ADDR(&mnid));
#endif
#endif

#if defined (USE_RADIUS)

  VALUE_PAIR *send, *received;
  VALUE_PAIR *vp;
  struct in6_addr prefix;
  uint32_t service;

  *aaa_result = 0;
  send = NULL;

  sprintf(g_username, "%04x%04x%04x%04x", ntohs(mnid.s6_addr16[4]), ntohs(mnid.s6_addr16[5]), ntohs(mnid.s6_addr16[6]), ntohs(mnid.s6_addr16[7]));
  g_username[16] = 0;
  memset(g_passwd, '\0', AUTH_PASS_LEN + 1);
  strncpy(g_passwd, conf.RadiusPassword, strlen(conf.RadiusPassword));
  g_passwd[strlen(conf.RadiusPassword)] = '\0';
  // Fill in User-Name

  strncpy(g_username_realm, g_username, sizeof(g_username_realm));

  // Append default realm
  if ((strchr(g_username_realm, '@') == NULL) && g_default_realm && (*g_default_realm != '\0')) {
    strncat(g_username_realm, "@", sizeof(g_username_realm) - strlen(g_username_realm) - 1);
    strncat(g_username_realm, g_default_realm, sizeof(g_username_realm) - strlen(g_username_realm) - 1);
  }

  dbg("RADIUS USER NAME %s\n", g_username_realm);
  dbg("RADIUS PASSWORD  %s\n", g_passwd);

  if (rc_avpair_add(g_rh, &send, PW_USER_NAME, g_username_realm, -1, 0) == NULL) {
    fprintf(stderr, "[RADIUS] ERROR rc_avpair_add PW_USER_NAME\n");
  } else {
    //
    // Fill in User-Password

    if (rc_avpair_add(g_rh, &send, PW_USER_PASSWORD, g_passwd, -1, 0) == NULL) {
      fprintf(stderr, "[RADIUS] ERROR rc_avpair_add PW_USER_PASSWORD\n");
    } else {

      // Fill in Service-Type

      service = PW_AUTHENTICATE_ONLY;

      if (rc_avpair_add(g_rh, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) {
        fprintf(stderr, "[RADIUS] ERROR rc_avpair_add PW_SERVICE_TYPE\n");
      } else {
        // result = RESULT always < 0 !!!
        rc_auth(g_rh, 0, send, &received, msg);
        {
          *aaa_result = 0;

          if (received != NULL) {
            if ((vp = rc_avpair_get(received, PW_FRAMED_IPV6_PREFIX, 0)) != NULL) {
              *aaa_result += 1;
              int netmask = vp->strvalue[1];
              int num_bytes = netmask / 8;
              int i;

              for (i = 0; i < num_bytes; i++) {
                prefix.s6_addr[i] = vp->strvalue[2 + i];
              }

              for (i = num_bytes; i < 16; i++) {
                prefix.s6_addr[i] = 0;
              }
            }

            if ((vp = rc_avpair_get(received, PW_FRAMED_INTERFACE_ID, 0)) != NULL) {
              *aaa_result += 1;
              int i;

              for (i = 0; i < 8; i++) {
                prefix.s6_addr[8 + i] = prefix.s6_addr[8 + i] | vp->strvalue[i];
              }
            }

            rc_avpair_free(received);
          }

          if (*aaa_result >= 2) {
            l_flag = 1;
            dbg("[RADIUS] Assigned IPv6 @ for MN UID %x:%x:%x:%x:%x:%x:%x:%x <=> %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&mnid), NIP6ADDR(&prefix));
            dbg("[RADIUS] \"%s\" Authentication OK\n", g_username);
            pmip_insert_into_hnp_cache(mnid, prefix);
            return prefix;
          }
        }
      }
    }
  }

#endif
  dbg("mnid not found\n");
  struct in6_addr tmp;
  memset(&tmp, 0, sizeof(struct in6_addr));
  *aaa_result = -1;
  return tmp;
}
{
    return IN6_IS_ADDR_LINKLOCAL(addr);
}


/*!
 * handler called when receiving a router solicitation
 */
//hip
static void pmip_mag_recv_rs(const struct icmp6_hdr *ih, __attribute__ ((unused)) ssize_t len, const struct in6_addr *saddr, const struct in6_addr *daddr, int iif, int hoplimit)
{
    dbg("\n");
    dbg("Router Solicitation received \n");
    printf("-------------------------------------\n");
    dbg("Router Solicitation (RS) Received iif %d\n", iif);
    dbg("Received RS Src Addr: %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(saddr));
    dbg("Received RS Dst addr: %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(daddr));
    msg_info_t rs_info;
    bzero(&rs_info, sizeof(rs_info));
    icmp_rs_parse(&rs_info, (struct nd_router_solicit *) ih, saddr, daddr, iif, hoplimit);
    mag_fsm(&rs_info);
}

/*!
 * handler called when receiving a proxy binding acknowledgment
 */
static void pmip_mag_recv_pba(const struct ip6_mh *mh, ssize_t len, const struct in6_addr_bundle *in_addrs, int iif)
{
    printf("=====================================\n");
    dbg("Proxy Binding Acknowledgement (PBA) Received\n");
    dbg("Received PBA Src Addr: %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(in_addrs->src));
Beispiel #23
0
void conf_show(struct mip6_config *c)
{
	int i;
	/* Common options */
	dbg("config_file = %s\n", c->config_file);
#ifdef ENABLE_VT
	dbg("vt_hostname = %s\n", c->vt_hostname);
	dbg("vt_service = %s\n", c->vt_service);
#endif
	dbg("mip6_entity = %u\n", c->mip6_entity);
	dbg("debug_level = %u\n", c->debug_level);
	dbg("debug_log_file = %s\n", (c->debug_log_file ? c->debug_log_file :
				      "stderr"));
	if (c->pmgr.so_path)
		dbg("PolicyModulePath = %s\n", c->pmgr.so_path);
	dbg("DefaultBindingAclPolicy = %u\n", c->DefaultBindingAclPolicy);
	dbg("NonVolatileBindingCache = %s\n",
	    CONF_BOOL_STR(c->NonVolatileBindingCache));
	
	/* IPsec options */
	dbg("KeyMngMobCapability = %s\n",
	    CONF_BOOL_STR(c->KeyMngMobCapability));
	dbg("UseMnHaIPsec = %s\n", CONF_BOOL_STR(c->UseMnHaIPsec));

	/* MN options */
	dbg("MnMaxHaBindingLife = %u\n", c->MnMaxHaBindingLife);
	dbg("MnMaxCnBindingLife = %u\n", c->MnMaxCnBindingLife);
	dbg("MnRouterProbes = %u\n", c->MnRouterProbes);
	dbg("MnRouterProbeTimeout = %f\n",
	    tstodsec(c->MnRouterProbeTimeout_ts));
	dbg("InitialBindackTimeoutFirstReg = %f\n", 
	    tstodsec(c->InitialBindackTimeoutFirstReg_ts));
	dbg("InitialBindackTimeoutReReg = %f\n", 
	    tstodsec(c->InitialBindackTimeoutReReg_ts));
	if (c->MoveModulePath)
		dbg("MoveModulePath = %s\n", c->MoveModulePath);
	dbg("UseCnBuAck = %s\n", CONF_BOOL_STR(c->CnBuAck));
	dbg("DoRouteOptimizationMN = %s\n",
	    CONF_BOOL_STR(c->DoRouteOptimizationMN));
	dbg("MnUseAllInterfaces = %s\n", CONF_BOOL_STR(c->MnUseAllInterfaces));
	dbg("MnDiscardHaParamProb = %s\n",
	    CONF_BOOL_STR(c->MnDiscardHaParamProb));
	dbg("SendMobPfxSols = %s\n", CONF_BOOL_STR(c->SendMobPfxSols));
	dbg("OptimisticHandoff = %s\n", CONF_BOOL_STR(c->OptimisticHandoff));
	dbg("MobRtrUseExplicitMode = %s\n",
	    CONF_BOOL_STR(c->MobRtrUseExplicitMode));

	/* HA options */
	dbg("SendMobPfxAdvs = %s\n", CONF_BOOL_STR(c->SendMobPfxAdvs));
	dbg("SendUnsolMobPfxAdvs = %s\n",
	    CONF_BOOL_STR(c->SendUnsolMobPfxAdvs));
	dbg("MaxMobPfxAdvInterval = %u\n", c->MaxMobPfxAdvInterval);
	dbg("MinMobPfxAdvInterval = %u\n", c->MinMobPfxAdvInterval);
	dbg("HaMaxBindingLife = %u\n", c->HaMaxBindingLife);
	dbg("HaAcceptMobRtr = %s\n", CONF_BOOL_STR(c->HaAcceptMobRtr));

	/* CN options */
	dbg("DoRouteOptimizationCN = %s\n",
	    CONF_BOOL_STR(c->DoRouteOptimizationCN));

	/* PMIP options */
	dbg("RFC5213TimestampBasedApproachInUse                = %s\n",CONF_BOOL_STR(c->RFC5213TimestampBasedApproachInUse));
	dbg("RFC5213MobileNodeGeneratedTimestampInUse          = %s\n",CONF_BOOL_STR(c->RFC5213MobileNodeGeneratedTimestampInUse));
	dbg("RFC5213FixedMAGLinkLocalAddressOnAllAccessLinks   = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->RFC5213FixedMAGLinkLocalAddressOnAllAccessLinks));
	dbg("RFC5213FixedMAGLinkLayerAddressOnAllAccessLinks   = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->RFC5213FixedMAGLinkLayerAddressOnAllAccessLinks));

	/* PMIP LMA options */
	dbg("RFC5213MinDelayBeforeBCEDelete                    = %u.%9u seconds\n",c->RFC5213MinDelayBeforeBCEDelete.tv_sec,c->RFC5213MinDelayBeforeBCEDelete.tv_nsec);
	dbg("RFC5213MaxDelayBeforeNewBCEAssign                 = %u.%9u seconds\n",c->RFC5213MaxDelayBeforeNewBCEAssign.tv_sec,c->RFC5213MaxDelayBeforeNewBCEAssign.tv_nsec);
	dbg("RFC5213TimestampValidityWindow                    = %u.%9u seconds\n",c->RFC5213TimestampValidityWindow.tv_sec,c->RFC5213TimestampValidityWindow.tv_nsec);

	/* PMIP MAG options */
	dbg("RFC5213EnableMAGLocalRouting = %s\n", CONF_BOOL_STR(c->RFC5213EnableMAGLocalRouting));

	dbg("AllLmaMulticastAddress            = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->AllLmaMulticastAddress));
	dbg("LmaAddress                        = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->LmaAddress));

	if (is_ha()) {
		for (i = 0; i < c->NumMags; i++) {
			dbg("MAG %d: \n", i);
			dbg("    MagAddressIngress                             = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->MagAddressIngress[i]));
			dbg("    MagAddressEgress                              = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->MagAddressEgress[i]));
		}
	}

	if (is_mag()) {
		dbg("MagAddressIngress                                 = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->MagAddressIngress[0]));
		dbg("MagAddressEgress                                  = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->MagAddressEgress[0]));
		dbg("MagDeviceIngress                  = %s\n", (c->MagDeviceIngress ? c->MagDeviceIngress : "No device"));
		dbg("MagDeviceEgress                   = %s\n", (c->MagDeviceEgress ? c->MagDeviceEgress : "No device"));
		dbg("PBULifeTime                       = %u.%9u seconds\n",c->PBULifeTime.tv_sec,c->PBULifeTime.tv_nsec);
		dbg("RetransmissionTimeOut             = %u.%9u seconds\n",c->RetransmissionTimeOut.tv_sec,c->RetransmissionTimeOut.tv_nsec);
		dbg("RadiusClientConfigFile            = %s\n", (c->RadiusClientConfigFile ? c->RadiusClientConfigFile : "No Config file"));
		dbg("RadiusPassword                    = %s\n", (c->RadiusPassword ? c->RadiusPassword : "******"));
		dbg("PcapSyslogAssociationGrepString   = %s\n", (c->PcapSyslogAssociationGrepString ? c->PcapSyslogAssociationGrepString : "No syslog association grep string"));
		dbg("PcapSyslogDeAssociationGrepString = %s\n", (c->PcapSyslogDeAssociationGrepString ? c->PcapSyslogDeAssociationGrepString : "No syslog de-association grep string"));
	}
	dbg("OurAddress                        = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->OurAddress));
	dbg("HomeNetworkPrefix                 = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->HomeNetworkPrefix));

	dbg("MaxMessageRetransmissions         = %u\n", c->MaxMessageRetransmissions);
	dbg("TunnelingEnabled                  = %s\n", CONF_BOOL_STR(c->TunnelingEnabled));
	dbg("DynamicTunnelingEnabled           = %s\n", CONF_BOOL_STR(c->DynamicTunnelingEnabled));
	dbg("MaxDelayBeforeDynamicTunnelingDelete              = %u.%9u seconds\n",c->MaxDelayBeforeDynamicTunnelingDelete.tv_sec,c->MaxDelayBeforeDynamicTunnelingDelete.tv_nsec);
}
int flowScheduler_link_down( ip6mn_nai_t mn_nai, struct in6_addr serving_mag){

    dbg("Link down - Rescheduling all flows from client [PUT NAI HERE] passing in MAG %x:%x:%x:%x:%x:%x:%x:%x \n",NIP6ADDR(&serving_mag));

    flowmob_cache_iterate(flowScheduler_change_mark, &mn_nai);

    dbg("Flows Rescheduled\n");
}
static int ndisc_send_unspec(int oif, const struct in6_addr *dest,
                             uint8_t *hdr, int hdrlen, struct iovec *optv,
                             size_t optvlen)
{
  struct {
    struct ip6_hdr ip;
    struct icmp6_hdr icmp;
    uint8_t data[1500];
  } frame;

  struct msghdr msgh;
  struct cmsghdr *cmsg;
  struct in6_pktinfo *pinfo;
  struct sockaddr_in6 dst;
  char cbuf[CMSG_SPACE(sizeof(*pinfo))];
  struct iovec iov;
  uint8_t *data = (uint8_t *)(&frame.icmp);
  int type, fd, ret, remlen, datalen = 0, written = 0, v = 1;

  if (hdr == NULL || hdrlen < 0 ||
      (size_t)hdrlen < sizeof(struct icmp6_hdr) ||
      (size_t)hdrlen > (sizeof(frame) - sizeof(struct ip6_hdr)))
    return -EINVAL;

  if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW)) < 0)
    return -1;

  if (setsockopt(fd, IPPROTO_IPV6, IP_HDRINCL, &v, sizeof(v)) < 0) {
    dbg("cannot set IP_HDRINCL: %s\n", strerror(errno));
    close(fd);
    return -errno;
  }

  memset(&frame, 0, sizeof(frame));
  memset(&dst, 0, sizeof(dst));

  dst.sin6_addr = *dest;

  /* Copy ICMPv6 header and update various length values */
  memcpy(data, hdr, hdrlen);
  data += hdrlen;
  datalen += hdrlen;
  remlen = sizeof(frame) - sizeof(struct ip6_hdr) - hdrlen;

  /* Prepare for csum: write trailing options by linearizing iov */
  if ((iov_linearize(data, remlen, optv, optvlen, &written) != 0) ||
      (written & 0x1)) /* Ensure length is even for csum() */
    return -1;

  datalen += written;

  /* Fill in the IPv6 header */
  frame.ip.ip6_vfc  = 0x60;
  frame.ip.ip6_plen = htons(datalen);
  frame.ip.ip6_nxt  = IPPROTO_ICMPV6;
  frame.ip.ip6_hlim = 255;
  frame.ip.ip6_dst  = *dest;
  /* all other fields are already set to zero */

  //frame.icmp.icmp6_cksum = in6_cksum(&in6addr_any, dest, &frame.icmp,
  //           datalen, IPPROTO_ICMPV6);
  frame.icmp.icmp6_cksum = csum_ipv6_magic(&in6addr_any, dest, datalen,
                           IPPROTO_ICMPV6,
                           csum_partial(&frame.icmp, datalen, 0));

  iov.iov_base = &frame;
  iov.iov_len = sizeof(frame.ip) + datalen;

  dst.sin6_family = AF_INET6;
  msgh.msg_name = &dst;
  msgh.msg_namelen = sizeof(dst);
  msgh.msg_iov = &iov;
  msgh.msg_iovlen = 1;
  msgh.msg_flags = 0;

  memset(cbuf, 0, CMSG_SPACE(sizeof(*pinfo)));
  cmsg = (struct cmsghdr *)cbuf;
  pinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
  pinfo->ipi6_ifindex = oif;

  cmsg->cmsg_len = CMSG_LEN(sizeof(*pinfo));
  cmsg->cmsg_level = IPPROTO_IPV6;
  cmsg->cmsg_type = IPV6_PKTINFO;
  msgh.msg_control = cmsg;
  msgh.msg_controllen = cmsg->cmsg_len;

  ret = sendmsg(fd, &msgh, 0);

  if (ret < 0)
    dbg("sendmsg: if index %u dest %x:%x:%x:%x:%x:%x:%x:%x: %s\n",
        oif,
        NIP6ADDR(dest),
        strerror(errno));

  close(fd);
  type = hdr[0];

  if (type == ND_NEIGHBOR_SOLICIT) {
    statistics_inc(&mipl_stat, MIPL_STATISTICS_OUT_NS_UNSPEC);
  } else if (type == ND_ROUTER_SOLICIT) {
    statistics_inc(&mipl_stat, MIPL_STATISTICS_OUT_RS_UNSPEC);
  }

  return ret;
}
void conf_show(struct mip6_config *c)
{
	/* Common options */
	dbg("config_file = %s\n", c->config_file);
#ifdef ENABLE_VT
	dbg("vt_hostname = %s\n", c->vt_hostname);
	dbg("vt_service = %s\n", c->vt_service);
#endif
	dbg("mip6_entity = %u\n", c->mip6_entity);
	dbg("debug_level = %u\n", c->debug_level);
	dbg("debug_log_file = %s\n", (c->debug_log_file ? c->debug_log_file :
				      "stderr"));
	if (c->pmgr.so_path)
		dbg("PolicyModulePath = %s\n", c->pmgr.so_path);
	dbg("DefaultBindingAclPolicy = %u\n", c->DefaultBindingAclPolicy);
	dbg("NonVolatileBindingCache = %s\n",
	    CONF_BOOL_STR(c->NonVolatileBindingCache));

	/* IPsec options */
	dbg("KeyMngMobCapability = %s\n",
	    CONF_BOOL_STR(c->KeyMngMobCapability));
	dbg("UseMnHaIPsec = %s\n", CONF_BOOL_STR(c->UseMnHaIPsec));

	/* MN options */
	dbg("MnMaxHaBindingLife = %u\n", c->MnMaxHaBindingLife);
	dbg("MnMaxCnBindingLife = %u\n", c->MnMaxCnBindingLife);
	dbg("MnRouterProbes = %u\n", c->MnRouterProbes);
	dbg("MnRouterProbeTimeout = %f\n",
	    tstodsec(c->MnRouterProbeTimeout_ts));
	dbg("InitialBindackTimeoutFirstReg = %f\n",
	    tstodsec(c->InitialBindackTimeoutFirstReg_ts));
	dbg("InitialBindackTimeoutReReg = %f\n",
	    tstodsec(c->InitialBindackTimeoutReReg_ts));
	if (c->MoveModulePath)
		dbg("MoveModulePath = %s\n", c->MoveModulePath);
	dbg("UseCnBuAck = %s\n", CONF_BOOL_STR(c->CnBuAck));
	dbg("DoRouteOptimizationMN = %s\n",
	    CONF_BOOL_STR(c->DoRouteOptimizationMN));
	dbg("MnUseAllInterfaces = %s\n", CONF_BOOL_STR(c->MnUseAllInterfaces));
	dbg("MnDiscardHaParamProb = %s\n",
	    CONF_BOOL_STR(c->MnDiscardHaParamProb));
	dbg("SendMobPfxSols = %s\n", CONF_BOOL_STR(c->SendMobPfxSols));
	dbg("OptimisticHandoff = %s\n", CONF_BOOL_STR(c->OptimisticHandoff));

	/* HA options */
	dbg("SendMobPfxAdvs = %s\n", CONF_BOOL_STR(c->SendMobPfxAdvs));
	dbg("SendUnsolMobPfxAdvs = %s\n",
	    CONF_BOOL_STR(c->SendUnsolMobPfxAdvs));
	dbg("MaxMobPfxAdvInterval = %u\n", c->MaxMobPfxAdvInterval);
	dbg("MinMobPfxAdvInterval = %u\n", c->MinMobPfxAdvInterval);
	dbg("HaMaxBindingLife = %u\n", c->HaMaxBindingLife);

    /* CN options */
    dbg("DoRouteOptimizationCN = %s\n",
        CONF_BOOL_STR(c->DoRouteOptimizationCN));


    /* PMIP options */
    dbg("AllLmaMulticastAddress    = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->AllLmaMulticastAddress));
    dbg("LmaAddress                = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->LmaAddress));
    if (is_mag()) {
    dbg("MagAddressIngress         = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->MagAddressIngress));
    dbg("MagAddressEgress          = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->MagAddressEgress));
	}
    dbg("OurAddress                = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->OurAddress));
    dbg("HomeNetworkPrefix         = %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(&c->HomeNetworkPrefix));

    dbg("PBULifeTime               = %u seconds\n",c->PBULifeTime.tv_sec);
    dbg("PBALifeTime               = %u seconds\n",c->PBALifeTime.tv_sec);
    dbg("NRetransmissionTime       = %u seconds\n",c->NRetransmissionTime.tv_sec);
    dbg("MaxMessageRetransmissions = %u\n", c->MaxMessageRetransmissions);
    dbg("TunnelingEnabled          = %s\n", CONF_BOOL_STR(c->TunnelingEnabled));
    dbg("DynamicTunnelingEnabled   = %s\n", CONF_BOOL_STR(c->DynamicTunnelingEnabled));
	dbg("RadiusClientConfigFile    = %s\n", (c->RadiusClientConfigFile ? c->RadiusClientConfigFile :
	"No Config file"));
	dbg("RadiusPassword            = %s\n", (c->RadiusPassword ? c->RadiusPassword :
	"******"));

}
int mh_bu_parse(struct ip6_mh_binding_update *bu, ssize_t len,
		const struct in6_addr_bundle *in_addrs,
		struct in6_addr_bundle *out_addrs,
		struct mh_options *mh_opts,
		struct timespec *lifetime, uint8_t *key)
{
	struct in6_addr *our_addr, *peer_addr, *remote_coa;
	struct ip6_mh_opt_altcoa *alt_coa;
	struct ip6_mh_opt_nonce_index *non_ind;
	struct ip6_mh_opt_auth_data *bauth;
	uint16_t bu_flags;
	int ret;

	MDBG("Binding Update Received\n");
	if (len < sizeof(struct ip6_mh_binding_update) ||
	    mh_opt_parse(&bu->ip6mhbu_hdr, len,
			 sizeof(struct ip6_mh_binding_update), mh_opts) < 0)
		return -1;

	peer_addr = in_addrs->src;
	if (!in6_is_addr_routable_unicast(peer_addr))
		return -1;

	remote_coa = in_addrs->remote_coa;
	if (remote_coa && !IN6_ARE_ADDR_EQUAL(remote_coa, peer_addr))
		out_addrs->remote_coa = remote_coa;
	else
		out_addrs->remote_coa = NULL;

	alt_coa = mh_opt(&bu->ip6mhbu_hdr, mh_opts, IP6_MHOPT_ALTCOA);
	if (alt_coa)
		out_addrs->bind_coa = &alt_coa->ip6moa_addr;
	else
		out_addrs->bind_coa = in_addrs->remote_coa;

	our_addr = in_addrs->dst;
	tsclear(*lifetime);
	if (out_addrs->bind_coa) {
		if (!in6_is_addr_routable_unicast(out_addrs->bind_coa))
			return -1;
		if (!IN6_ARE_ADDR_EQUAL(out_addrs->bind_coa, peer_addr)) {
			/* check that there is no circular reference */
			if (bce_exists(our_addr, out_addrs->bind_coa))
				return -1;
			tssetsec(*lifetime, ntohs(bu->ip6mhbu_lifetime) << 2);
		}
	}
	/* Use Home address of MN for calculating BU and BA auth data
	 * for deregs. */
	if (!out_addrs->bind_coa)
		out_addrs->bind_coa = in_addrs->src;

	bu_flags = bu->ip6mhbu_flags;
	out_addrs->src = in_addrs->dst;
	out_addrs->dst = in_addrs->src;
	out_addrs->local_coa = NULL;

	non_ind = mh_opt(&bu->ip6mhbu_hdr, mh_opts, IP6_MHOPT_NONCEID);

	if (bu_flags & IP6_MH_BU_HOME)
		return non_ind ? -1 : 0;

	if (!non_ind)
		return -1;

	MDBG("src %x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(peer_addr));
	MDBG("coa %x:%x:%x:%x:%x:%x:%x:%x\n",
	     NIP6ADDR(out_addrs->bind_coa));

	if (tsisset(*lifetime))
		ret = rr_cn_calc_Kbm(ntohs(non_ind->ip6moni_home_nonce),
				     ntohs(non_ind->ip6moni_coa_nonce),
				     peer_addr, out_addrs->bind_coa, key);
	else /* Only use home nonce and address for dereg. */
		ret = rr_cn_calc_Kbm(ntohs(non_ind->ip6moni_home_nonce), 0,
				     peer_addr, NULL, key);
	if (ret)
		return ret;

	bauth = mh_opt(&bu->ip6mhbu_hdr, mh_opts, IP6_MHOPT_BAUTH);
	if (!bauth)
		return -1;
	/* Authenticator is calculated with MH checksum set to 0 */
	bu->ip6mhbu_hdr.ip6mh_cksum = 0;
	if (mh_verify_auth_data(bu, len, bauth,
				out_addrs->bind_coa, our_addr, key) < 0)
		return -1;

	return IP6_MH_BAS_ACCEPTED;
}
//---------------------------------------------------------------------------
// Search the sending function for IP Packet
void nasrg_CLASS_send(struct sk_buff *skb)
{
  //---------------------------------------------------------------------------
  struct classifier_entity  *pclassifier, *sp;
  uint8_t *protocolh = NULL;
  uint8_t version;
  uint8_t protocol, dscp;
  uint16_t classref;
  struct cx_entity *cx;
  unsigned int i;
#ifdef NAS_DEBUG_CLASS
  char sfct[10], sprotocol[10];
#endif
  struct net_device *dev = gdev;
  unsigned char cx_index,no_connection;
  int addr_type;
  int mbms_ix;
  struct in6_addr masked6_addr;
  struct in_addr  masked_addr;
  // RARP vars
  struct arphdr  *rarp;
  unsigned char  *rarp_ptr;
  /* s for "source", t for "target" */
  __be32 sip, tip;
  unsigned char *sha, *tha;

#ifdef NAS_DEBUG_CLASS
  printk("nasrg_CLASS_send: begin -\n");
#endif

  if (skb==NULL) {
    printk("nasrg_CLASS_send - input parameter skb is NULL \n");
    return;
  }

  //***
#ifdef NAS_DEBUG_SEND
  printk("nasrg_CLASS_send - Received IP packet to transmit, length %d\n", skb->len);
#endif
#ifdef NAS_DEBUG_SEND_DETAIL

  if ((skb->data) != NULL) {
    if (skb->len<150)
      nasrg_TOOL_print_buffer(skb->data,skb->len);
    else
      nasrg_TOOL_print_buffer(skb->data,150);
  }

#endif
  //***
  // find all connections related to socket
  cx_index   = 0;
  no_connection = 1;
  cx = NULL;
#ifdef NAS_DEBUG_CLASS
  printk("nasrg_CLASS_send: [before switch on IP protocol version] \n");
#endif


  // Get mobile connexion entity, protocol and dscp from IP packet
  switch (ntohs(skb->protocol)) {
  case ETH_P_IPV6:
#ifdef NAS_DEBUG_CLASS_DETAIL
    printk("nasrg_CLASS_send : skb->protocol : IPv6 \n");
#endif
    version = NAS_VERSION_6;
    addr_type = NAS_IPV6_ADDR_UNKNOWN;
    protocolh = nasrg_TOOL_get_protocol6(ipv6_hdr(skb), &protocol);
    dscp      = nasrg_TOOL_get_dscp6 (ipv6_hdr(skb));
    cx        = nasrg_CLASS_cx6 (skb, dscp, &addr_type, &cx_index, &mbms_ix);
#ifdef NAS_DEBUG_CLASS_DETAIL
    printk("nasrg_CLASS_send - ETH_P_IPV6 skb %p dscp %d gpriv %p cx_index %p \n",skb, dscp, gpriv, &cx_index);
#endif

    // find in default DSCP a valid classification
    if (cx == NULL) {
      switch (addr_type) {
      case NAS_IPV6_ADDR_MC_SIGNALLING:
      case NAS_IPV6_ADDR_UNICAST:
#ifdef NAS_DEBUG_CLASS_DETAIL
        printk("nasrg_CLASS_send - case NAS_IPV6_ADDR_MC_SIGNALLING | NAS_IPV6_ADDR_UNICAST\n");
#endif //NAS_DEBUG_CLASS

        for (i=0; i<NAS_CX_MAX; i++) {
          pclassifier=(&gpriv->cx[i])->sclassifier[NAS_DSCP_DEFAULT];

          while (pclassifier!=NULL) {
            if ((pclassifier->version == NAS_VERSION_6) || (pclassifier->version == NAS_VERSION_DEFAULT)) {
              // ok found default classifier for this packet
              nasrg_create_mask_ipv6_addr(&masked6_addr, pclassifier->dplen);
              // Modified MW to let everything go (pb with signalling)
              masked6_addr.s6_addr32[0] = 0x00000000;
              masked6_addr.s6_addr32[1] = 0x00000000;
#ifdef NAS_DEBUG_CLASS_DETAIL
              printk("nasrg_CLASS_send - cx %d : DSCP NAS_DSCP_DEFAULT %X:%X:%X:%X:%X:%X:%X:%X\n",i, NIP6ADDR(&(pclassifier->daddr.ipv6)));
#endif //NAS_DEBUG_CLASS

              if (IN6_ARE_ADDR_MASKED_EQUAL(&pclassifier->daddr.ipv6, &ipv6_hdr(skb)->daddr, &masked6_addr)) {
                // then force dscp
                cx = &gpriv->cx[i];
#ifdef NAS_DEBUG_CLASS
                printk("nasrg_CLASS_send - ETH_P_IPV6 FOUND NAS_DSCP_DEFAULT with IN6_ARE_ADDR_MASKED_EQUAL(%d bits)\n",pclassifier->dplen);
#endif
                dscp = NAS_DSCP_DEFAULT;
                break;
              } else {
                if(IN6_IS_ADDR_UNSPECIFIED(&pclassifier->daddr.ipv6)) {
                  cx = &gpriv->cx[i];
#ifdef NAS_DEBUG_CLASS
                  printk("nasrg_CLASS_send - ETH_P_IPV6 FOUND NAS_DSCP_DEFAULT with IN6_IS_ADDR_UNSPECIFIED\n");
#endif
                  dscp = NAS_DSCP_DEFAULT;
                  break;
                }
              }
            }

            pclassifier = pclassifier->next;
          }
        }

        break;

        // MBMS is broken!!!! To be updated (these values will be over-ridden afterwards
      case NAS_IPV6_ADDR_MC_MBMS:
#ifdef NAS_DEBUG_CLASS
        printk("nasrg_CLASS_send - case NAS_IPV6_ADDR_MC_MBMS\n");
#endif //NAS_DEBUG_CLASS
        pclassifier = gpriv->mbmsclassifier[mbms_ix];
        printk("nasrg_CLASS_send: MBMS is broken!!!!\n\n\n");
        sp = gpriv->mbmsclassifier[mbms_ix];

        if (sp!= NULL) {
          classref=sp->classref;
#ifdef NAS_DEBUG_CLASS_DETAIL
          printk("nasrg_CLASS_send: classifier found for multicast service %d \n", mbms_ix);
#endif
        } else {
          printk("nasrg_CLASS_send: No corresponding multicast bearer, so the message is dropped\n");
          return;
        }

        break;

        // should have found a valid classification rule
      case NAS_IPV6_ADDR_UNKNOWN:
      default:
        printk("nasrg_CLASS_send: No corresponding address type\n");
      }
    }

    break;

  case ETH_P_ARP:
#ifdef NAS_DEBUG_CLASS
    printk("nasrg_CLASS_send : skb->protocol : ARP \n");
#endif
    version = NAS_VERSION_4;
    addr_type = NAS_IPV4_ADDR_BROADCAST;
    dscp = 0;
    cx = NULL;
    // Basic sanity checks can be done without the lock
    rarp = (struct arphdr *)skb_network_header(skb);

    if (rarp) {
      if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd)) {
        printk("nasrg_CLASS_send: ARP PACKET WRONG ADDR LEN or WRONG ARP HEADER TYPE\n");
        break;
      }
    } else {
      printk("nasrg_CLASS_send: ARP HEADER POINTER IS NULL\n");
      break;
    }

    // If it's not Ethernet, delete it.
    if (rarp->ar_pro != htons(ETH_P_IP)) {
      printk("nasrg_CLASS_send: ARP PACKET PROTOCOL IS NOT ETHERNET\n");
      break;
    }

    rarp_ptr = (unsigned char *) (rarp + 1);
    sha = rarp_ptr;
    rarp_ptr += dev->addr_len;
    memcpy(&sip, rarp_ptr, 4);
    rarp_ptr += 4;
    tha = rarp_ptr;
    rarp_ptr += dev->addr_len;
    memcpy(&tip, rarp_ptr, 4);
#ifdef NAS_DEBUG_CLASS
    printk("nasrg_CLASS_send: ARP DEST IP transport IP = %d.%d.%d.%d\n",NIPADDR(tip));
#endif

    for (i=0; i<NAS_CX_MAX; i++) {
      pclassifier=(&gpriv->cx[i])->sclassifier[NAS_DSCP_DEFAULT];

      while (pclassifier!=NULL) {
        if ((pclassifier->version == NAS_VERSION_4) || (pclassifier->version == NAS_VERSION_DEFAULT)) {
          // ok found default classifier for this packet
          nasrg_create_mask_ipv4_addr(&masked_addr, pclassifier->dplen);
#ifdef NAS_DEBUG_CLASS
          printk("nasrg_CLASS_send: MASK = %d.%d.%d.%d\n",NIPADDR(masked_addr.s_addr));
#endif

          //
          if (IN_ARE_ADDR_MASKED_EQUAL(&pclassifier->daddr.ipv4, &tip, &masked_addr.s_addr)) {
            // then force dscp
            cx = &gpriv->cx[i];
#ifdef NAS_DEBUG_CLASS
            printk("nasrg_CLASS_send: ETH_P_ARP FOUND NAS_DSCP_DEFAULT with IN_ARE_ADDR_MASKED_EQUAL(%d bits)\n", pclassifier->dplen);
#endif
            dscp = NAS_DSCP_DEFAULT;
            break;
          } else {
            if (INADDR_ANY == pclassifier->daddr.ipv4) {
              cx = &gpriv->cx[i];
#ifdef NAS_DEBUG_CLASS
              printk("nasrg_CLASS_send: ETH_P_ARP FOUND NAS_DSCP_DEFAULT with INADDR_ANY\n");
#endif
              dscp = NAS_DSCP_DEFAULT;
              break;
            }
          }
        }

        pclassifier = pclassifier->next;
      }
    }

    break;

  case ETH_P_IP:
#ifdef NAS_DEBUG_CLASS_DETAIL
    printk("nasrg_CLASS_send : skb->protocol : IPv4 \n");
#endif
    version   = NAS_VERSION_4;
    addr_type = NAS_IPV4_ADDR_UNKNOWN;
    dscp      = nasrg_TOOL_get_dscp4((struct iphdr *)(skb_network_header(skb)));
    cx        = nasrg_CLASS_cx4(skb, dscp, &addr_type, &cx_index);
    protocolh = nasrg_TOOL_get_protocol4((struct iphdr *)(skb_network_header(skb)), &protocol);

    // find in default DSCP a valid classification
    if (cx == NULL) {
      switch (addr_type) {
      case NAS_IPV4_ADDR_MC_SIGNALLING:
      case NAS_IPV4_ADDR_UNICAST:
      case NAS_IPV4_ADDR_BROADCAST:
        for (i=0; i<NAS_CX_MAX; i++) {
          pclassifier=(&gpriv->cx[i])->sclassifier[NAS_DSCP_DEFAULT];

          while (pclassifier != NULL) {
            if ((pclassifier->version == NAS_VERSION_4) || (pclassifier->version == NAS_VERSION_DEFAULT)) {
              // ok found default classifier for this packet
              nasrg_create_mask_ipv4_addr(&masked_addr, pclassifier->dplen);
#ifdef NAS_DEBUG_CLASS_DETAIL
              printk("nasrg_CLASS_send : MASK = %d.%d.%d.%d\n", NIPADDR(masked_addr.s_addr));
#endif

              if (IN_ARE_ADDR_MASKED_EQUAL(&pclassifier->daddr.ipv4, &ip_hdr(skb)->daddr, &masked_addr.s_addr)) {
                // then force dscp
                cx = &gpriv->cx[i];
#ifdef NAS_DEBUG_CLASS
                printk("nasrg_CLASS_send : ETH_P_IP FOUND NAS_DSCP_DEFAULT with IN_ARE_ADDR_MASKED_EQUAL(%d bits)\n",pclassifier->dplen);
#endif
                dscp = NAS_DSCP_DEFAULT;
                break;
              } else {
                if(INADDR_ANY == pclassifier->daddr.ipv4) {
                  cx = &gpriv->cx[i];
#ifdef NAS_DEBUG_CLASS
                  printk("nasrg_CLASS_send : ETH_P_IP FOUND NAS_DSCP_DEFAULT with INADDR_ANY\n");
#endif
                  dscp = NAS_DSCP_DEFAULT;
                  break;
                }
              }
            }

            pclassifier = pclassifier->next;
          }
        }

        break;

        // should have found a valid classification rule
      case NAS_IPV4_ADDR_UNKNOWN:
      default:
        printk("nasrg_CLASS_send: No corresponding address type\n");
      }
    }

#ifdef NAS_DEBUG_CLASS

    if (cx)
      printk("nasrg_CLASS_send: ETH_P_IP Received IPv4 packet (%02X), dscp = %d, cx = %d\n",ntohs(skb->protocol),dscp,cx->lcr);
    else
      printk("nasrg_CLASS_send: ETH_P_IP Received IPv4 packet (%02X), dscp = %d, No valid connection\n",ntohs(skb->protocol),dscp);

#endif
    break;

  default:
    printk("nasrg_CLASS_send: Unknown IP version protocol\n");
    version = 0;
    return;
  }

#ifdef NAS_DEBUG_CLASS_DETAIL
  printk("nasrg_CLASS_send: [before if (cx != NULL)]\n");
#endif

  //Next lines bypass classifiers to test the netlink socket
  //#define DEBUG_NETLINKRG_TEST
#ifdef DEBUG_NETLINKRG_TEST
  nasrg_COMMON_QOS_send_test_netlink(skb);
  return;
#endif

  // If a valid connection for the DSCP/EXP with destination address
  // is found scan all protocol-based classification rules
  if (cx != NULL) {
    classref = 0;
    sp = NULL;

    if (cx->state!=NAS_CX_DCH) {
#ifdef NAS_DEBUG_CLASS
      printk("nasrg_CLASS_send: UE not connected, in state %d. Packet is dropped\n",cx->state);
#endif
      return;
    }

    if (addr_type==NAS_IPV6_ADDR_MC_MBMS) {
      sp = gpriv->mbmsclassifier[mbms_ix];

      if (sp!= NULL) {
        classref=sp->classref;
#ifdef NAS_DEBUG_CLASS
        printk("nasrg_CLASS_send: classifier found for multicast index %d, service %d\n", mbms_ix, gpriv->mbms_rb[mbms_ix].cnxid);
#endif
      } else {
        // Temp MEDIEVAL : use default classifier
        sp = cx->sclassifier[NAS_DSCP_DEFAULT];

        if (sp!= NULL) {
          classref=sp->classref;
#ifdef NAS_DEBUG_CLASS
          printk("nasrg_CLASS_send: classifier for multicast service %d replaced by default %d\n", mbms_ix, classref);
#endif
#ifdef NAS_AUTO_MBMS
          nasrg_ASCTL_start_default_mbms_service();
#endif
        } else {
          printk("nasrg_CLASS_send: No corresponding multicast bearer, so the message is dropped\n");
          return;
        }
      }
    } else {
#ifdef NAS_DEBUG_CLASS_DETAIL
      printk("nasrg_CLASS_send: DSCP %d version %d: looking for classifier entry\n",dscp, version);
#endif

      for (pclassifier=cx->sclassifier[dscp]; pclassifier!=NULL; pclassifier=pclassifier->next) {
#ifdef NAS_DEBUG_CLASS_DETAIL
        printk("nasrg_CLASS_send: DSCP %d p->classref=%d,p->protocol=%d,p->version=%d\n",dscp,pclassifier->classref,pclassifier->protocol,pclassifier->version);
#endif

        // normal rule checks that network protocol version matches
        if ((pclassifier->version == version)  || (pclassifier->version == NAS_VERSION_DEFAULT)) {
          //printk("nasrg_CLASS_send: IP version are equals\n");
          sp=pclassifier;
          classref=sp->classref;
#ifdef NAS_DEBUG_CLASS_DETAIL
          printk("nasrg_CLASS_send: classifier found for dscp %u \n", dscp);
#endif
          break;
        }
      }
    }

    if (sp!=NULL) {
#ifdef NAS_DEBUG_CLASS

      //char sfct[10], sprotocol[10];
      // classifier entity found. Print its parameters
      if (sp->fct==nasrg_COMMON_QOS_send)
        strcpy(sfct, "data xfer");

      if (sp->fct==nasrg_CTL_send)
        strcpy(sfct, "iocontrol");

      if (sp->fct==nasrg_COMMON_del_send)
        strcpy(sfct, "delete");

      if (sp->fct==nasrg_ASCTL_DC_send_sig_data_request)
        strcpy(sfct, "DC-SAP");

      switch(protocol) {
      case NAS_PROTOCOL_UDP:
        strcpy(sprotocol, "udp");
        printk("udp packet\n");
        break;

      case NAS_PROTOCOL_TCP:
        strcpy(sprotocol, "tcp");
        printk("tcp packet\n");
        break;

      case NAS_PROTOCOL_ICMP4:
        strcpy(sprotocol, "icmp4");
        printk("icmp4 packet\n");
        break;

      case NAS_PROTOCOL_ICMP6:
        strcpy(sprotocol, "icmp6");
        nasrg_TOOL_pk_icmp6((struct icmp6hdr*)protocolh);
        break;

      default:
        strcpy(sprotocol, "other L4");
        break;
      }

      printk("nasrg_CLASS_send: (dscp %u, %s) received, (classref %u, fct %s, drb_id %u) classifier rule\n",
             dscp, sprotocol, sp->classref, sfct, sp->rab_id);
#endif

      //forward packet to the correct entity
      if (sp->fct!=NULL) {
        sp->fct(skb, cx, sp);
      } else {
        printk("\n\nnasrg_CLASS_send: ERROR : CLASSIFIER FUNCTION IS NULL\n\n");
      }

      no_connection = 0;
      // end : if classifier entry match found
    } else {
      printk("nasrg_CLASS_send: no corresponding item in the classifier list, so the message is dropped\n");
      printk("nasrg_CLASS_send: packet parameters: dscp %u, %s\n", dscp, sprotocol);
      nasrg_COMMON_del_send(skb, cx, NULL);  // Note MW: LG has commented this line. Why?
    }
  }   // if connection found

#ifdef NAS_DEBUG_CLASS

  if (no_connection == 1) {
    printk("nasrg_CLASS_send: no corresponding connection, so the message is dropped\n");
  }

#endif
#ifdef NAS_DEBUG_CLASS_DETAIL
  printk("nasrg_CLASS_send: end\n");
#endif
}
/**
 * mh_send - send mobility header message
 * @addrs: bundle of addresses
 * @mh_vec: scatter/gather array
 * @iovlen: array block count
 * @bind_key: key for calculating binding auth. data
 *
 * Sends a mobility header message to @dst with @src source address.
 * Mobility header is created from the @mh_vec vector array created by
 * the caller and initialized with mh_create() and mh_create_opt_*()
 * calls.  Padding is done automatically and mobility header length is
 * set.  Binding authorization data is calculated if present.  Returns
 * number of bytes sent on success, otherwise negative error value.
 **/
int mh_send(const struct in6_addr_bundle *addrs, const struct iovec *mh_vec,
	    int iovlen, const uint8_t *bind_key, int oif)
{
	struct ip6_mh_opt_auth_data lbad;
	struct sockaddr_in6 daddr;

	struct iovec iov[2*(IP6_MHOPT_MAX+1)];
	struct msghdr msg;
	struct cmsghdr *cmsg;
	int cmsglen;
	struct in6_pktinfo pinfo;
	int ret = 0, on = 1;
	struct ip6_mh *mh;
	int iov_count;
	socklen_t rthlen = 0;

	iov_count = mh_try_pad(mh_vec, iov, iovlen);
	mh = (struct ip6_mh *)iov[0].iov_base;
	mh->ip6mh_hdrlen = (mh_length(iov, iov_count) >> 3) - 1;

	/*
	 * We use MH out policy for all address. Then we should update it
	 * to refresh its bundle in kernel to be used with correct
	 * route, IPsec SA and neighbor cache entry for the destination.
	 * IKE daemon does the same thing for rekeying process.
	 */
        if (xfrm_cn_policy_mh_out_touch(1) < 0) {
                MDBG("MH out policy touch failed: BA for "
                     "%x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(addrs->dst));
        }

	MDBG("sending MH type %d\n"
	     "from %x:%x:%x:%x:%x:%x:%x:%x\n"
	     "to %x:%x:%x:%x:%x:%x:%x:%x\n",
	     mh->ip6mh_type, NIP6ADDR(addrs->src), NIP6ADDR(addrs->dst));

	if (addrs->local_coa)
		MDBG("local CoA %x:%x:%x:%x:%x:%x:%x:%x\n",
		     NIP6ADDR(addrs->local_coa));

	if (addrs->remote_coa)
		MDBG("remote CoA %x:%x:%x:%x:%x:%x:%x:%x\n",
		     NIP6ADDR(addrs->remote_coa));

	if (bind_key) {
		assert(iov_count > 1);
		struct ip6_mh_opt_auth_data *bauth;
		struct iovec *biov;
		struct in6_addr *cn = NULL;
		MDBG("Adding bind auth data\n");
		if (mh->ip6mh_type == IP6_MH_TYPE_BU)
			cn = addrs->dst;
		else
			cn = addrs->src;
		assert(addrs->bind_coa != NULL && cn != NULL);
		biov = &iov[iov_count - 1];
		bauth = (struct ip6_mh_opt_auth_data *)biov->iov_base;

		if (bauth->ip6moad_type == IP6_MHOPT_BAUTH) {
			size_t orig_len = biov->iov_len;

			MDBG("Adding auth_data\n");
			memcpy(&lbad, bauth, sizeof(lbad));

			/* temporarily set iov_len to option header
			 * length for auth data calculation */
			biov->iov_len -= MIPV6_DIGEST_LEN;
			biov->iov_base = &lbad;
			calculate_auth_data(iov, iov_count, addrs->bind_coa,
					    cn, bind_key, lbad.ip6moad_data);
			biov->iov_len = orig_len;
		}
	}

	memset(&daddr, 0, sizeof(struct sockaddr_in6));
	daddr.sin6_family = AF_INET6;
	daddr.sin6_addr = *addrs->dst;
	daddr.sin6_port = htons(IPPROTO_MH);

	memset(&pinfo, 0, sizeof(pinfo));
	pinfo.ipi6_addr = *addrs->src;
	pinfo.ipi6_ifindex = oif;

	cmsglen = CMSG_SPACE(sizeof(pinfo));
	if (addrs->remote_coa != NULL) {
		rthlen = inet6_rth_space(IPV6_RTHDR_TYPE_2, 1);
		if (!rthlen) {
			MDBG("inet6_rth_space error\n");
			return -1;
		}
		cmsglen += CMSG_SPACE(rthlen);
	}
	cmsg = malloc(cmsglen);
	if (cmsg == NULL) {
		MDBG("malloc failed\n");
		return -ENOMEM;
	}
	memset(cmsg, 0, cmsglen);
	memset(&msg, 0, sizeof(msg));

	msg.msg_control = cmsg;
	msg.msg_controllen = cmsglen;
	msg.msg_iov = iov;
	msg.msg_iovlen = iov_count;
	msg.msg_name = (void *)&daddr;
	msg.msg_namelen = sizeof(daddr);

	cmsg = CMSG_FIRSTHDR(&msg);
	cmsg->cmsg_len = CMSG_LEN(sizeof(pinfo));
	cmsg->cmsg_level = IPPROTO_IPV6;
	cmsg->cmsg_type = IPV6_PKTINFO;
	memcpy(CMSG_DATA(cmsg), &pinfo, sizeof(pinfo));

	if (addrs->remote_coa != NULL) {
		void *rthp;

		cmsg = CMSG_NXTHDR(&msg, cmsg);
		if (cmsg == NULL) {
			free(msg.msg_control);
			MDBG("internal error\n");
			return -2;
		}
		cmsg->cmsg_len = CMSG_LEN(rthlen);
		cmsg->cmsg_level = IPPROTO_IPV6;
		cmsg->cmsg_type = IPV6_RTHDR;
		rthp = CMSG_DATA(cmsg);
		rthp = inet6_rth_init(rthp, rthlen, IPV6_RTHDR_TYPE_2, 1);
		if (rthp == NULL) {
			free(msg.msg_control);
			MDBG("inet6_rth_init error\n");
			return -3;
		}
		inet6_rth_add(rthp, addrs->remote_coa);
		rthp = NULL;
	}

	pthread_mutex_lock(&mh_sock.send_mutex);
	setsockopt(mh_sock.fd, IPPROTO_IPV6, IPV6_PKTINFO,
		   &on, sizeof(int));
	ret = sendmsg(mh_sock.fd, &msg, 0);
	if (ret < 0)
		dbg("sendmsg: %s\n", strerror(errno));

	pthread_mutex_unlock(&mh_sock.send_mutex);

	free(msg.msg_control);

	return ret;
}