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