/******************************************************************************* Eurecom OpenAirInterface 2 Copyright(c) 1999 - 2010 Eurecom This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information Openair Admin: openair_admin@eurecom.fr Openair Tech : openair_tech@eurecom.fr Forums : http://forums.eurecom.fsr/openairinterface Address : Eurecom, 2229, route des crĂȘtes, 06560 Valbonne Sophia Antipolis, France *******************************************************************************/ #include "local.h" #include "proto_extern.h" //#include //#include //#include //#include //#include //#include //#define KERNEL_VERSION_GREATER_THAN_2622 1 //#define KERNEL_VERSION_GREATER_THAN_2630 1 //#define NAS_DEBUG_TOOL 1 //--------------------------------------------------------------------------- // void nas_TOOL_fct(struct classifier_entity *gc, uint8_t fct){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_FCT - begin \n"); #endif if (gc==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_FCT - input parameter gc is NULL \n"); #endif return; } // End debug information switch(fct){ case NAS_FCT_QOS_SEND: gc->fct=nas_COMMON_QOS_send; break; case NAS_FCT_CTL_SEND: gc->fct=nas_CTL_send; break; case NAS_FCT_DC_SEND: gc->fct=nas_mesh_DC_send_sig_data_request; break; case NAS_FCT_DEL_SEND: gc->fct=nas_COMMON_del_send; break; default: gc->fct=nas_COMMON_del_send; } } //--------------------------------------------------------------------------- uint8_t nas_TOOL_invfct(struct classifier_entity *gc){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_INVFCT - begin \n"); #endif if (gc==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_INVFCT - input parameter gc is NULL \n"); #endif return 0; } // End debug information if (gc->fct==nas_COMMON_QOS_send) return NAS_FCT_QOS_SEND; if (gc->fct==nas_CTL_send) return NAS_FCT_CTL_SEND; if (gc->fct==nas_COMMON_del_send) return NAS_FCT_DEL_SEND; if (gc->fct==nas_mesh_DC_send_sig_data_request) return NAS_FCT_DC_SEND; return 0; } //--------------------------------------------------------------------------- uint8_t nas_TOOL_get_dscp6(struct ipv6hdr *iph){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_GET_DSCP6 - begin \n"); #endif if (iph==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_GET_DSCP6 - input parameter iph is NULL \n"); #endif return 0; } // End debug information return (ntohl(((*(__u32 *)iph)&NAS_TRAFFICCLASS_MASK)))>>22; //return ntohs(*(const __be16 *)iph) >> 4; // see linux/dsfield.h } //--------------------------------------------------------------------------- uint8_t nas_TOOL_get_dscp4(struct iphdr *iph){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_GET_DSCP4 - begin \n"); #endif if (iph==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_GET_DSCP4 - input parameter iph is NULL \n"); #endif return 0; } // End debug information return (iph->tos); } //--------------------------------------------------------------------------- int nas_TOOL_network6(struct in6_addr *addr, struct in6_addr *prefix, uint8_t plen){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_NETWORK6 - begin \n"); #endif if (addr==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_NETWORK6 - input parameter addr is NULL \n"); #endif return 0; } if (prefix==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_NETWORK6 - input parameter prefix is NULL \n"); #endif return 0; } // End debug information switch(plen/32) { case 0: return (((addr->s6_addr32[0]>>(32-plen))<<(32-plen))==prefix->s6_addr[0]); case 1: return ((addr->s6_addr32[0]==prefix->s6_addr[0])&& (((addr->s6_addr32[1]>>(64-plen))<<(64-plen))==prefix->s6_addr[1])); case 2: return ((addr->s6_addr32[0]==prefix->s6_addr[0])&& (addr->s6_addr32[1]==prefix->s6_addr[1])&& (((addr->s6_addr32[2]>>(96-plen))<<(96-plen))==prefix->s6_addr[2])); case 3: return ((addr->s6_addr32[0]==prefix->s6_addr[0])&& (addr->s6_addr32[1]==prefix->s6_addr[1])&& (addr->s6_addr32[2]==prefix->s6_addr[2])&& (((addr->s6_addr32[3]>>(128-plen))<<(128-plen))==prefix->s6_addr[3])); default: return ((addr->s6_addr32[0]==prefix->s6_addr[0])&& (addr->s6_addr32[1]==prefix->s6_addr[1])&& (addr->s6_addr32[2]==prefix->s6_addr[2])&& (addr->s6_addr32[3]==prefix->s6_addr[3])); } } //--------------------------------------------------------------------------- int nas_TOOL_network4(uint32_t *addr, uint32_t *prefix, uint8_t plen){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_NETWORK4 - begin \n"); #endif if (addr==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_NETWORK4 - input parameter addr is NULL \n"); #endif return 0; } if (prefix==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_NETWORK4 - input parameter prefix is NULL \n"); #endif return 0; } // End debug information if (plen>=32) return (*addr==*prefix); else return (((*addr>>(32-plen))<<(32-plen))==*prefix); } //--------------------------------------------------------------------------- //struct udphdr *nas_TOOL_get_udp6(struct ipv6hdr *iph){ //--------------------------------------------------------------------------- // return (struct udphdr *)((char *)iph+NAS_IPV6_SIZE); // to modify //} //--------------------------------------------------------------------------- uint8_t *nas_TOOL_get_protocol6(struct ipv6hdr *iph, uint8_t *protocol){ //--------------------------------------------------------------------------- uint16_t size; // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_GET_PROTOCOL6 - begin \n"); #endif if (iph==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_GET_PROTOCOL6 - input parameter iph is NULL \n"); #endif return NULL; } if (protocol==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_GET_PROTOCOL6 - input parameter protocol is NULL \n"); #endif return NULL; } // End debug information *protocol=iph->nexthdr; size=NAS_IPV6_SIZE; while (1) { switch(*protocol) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_ICMPV6: return (uint8_t *)((uint8_t *)iph+size); case IPPROTO_HOPOPTS: case IPPROTO_ROUTING: case IPPROTO_DSTOPTS: *protocol=((uint8_t *)iph+size)[0]; size+=((uint8_t *)iph+size)[1]*8+8; break; case IPPROTO_FRAGMENT: *protocol=((uint8_t *)iph+size)[0]; size+=((uint8_t *)iph+size)[1]+8; break; case IPPROTO_NONE: case IPPROTO_AH: case IPPROTO_ESP: default: return NULL; } } } //--------------------------------------------------------------------------- uint8_t *nas_TOOL_get_protocol4(struct iphdr *iph, uint8_t *protocol){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_GET_PROTOCOL4 - begin \n"); #endif if (iph==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_GET_PROTOCOL4 - input parameter iph is NULL \n"); #endif return NULL; } if (protocol==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_GET_PROTOCOL4 - input parameter protocol is NULL \n"); #endif return NULL; } // End debug information *protocol=iph->protocol; switch(*protocol) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_ICMP: return (uint8_t *)((uint8_t *)iph+iph->tot_len); default: return NULL; } } //--------------------------------------------------------------------------- // Convert the IMEI to iid void nas_TOOL_imei2iid(uint8_t *imei, uint8_t *iid){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_IMEI2IID - begin \n"); #endif if (imei==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_IMEI2IID - input parameter imei is NULL \n"); #endif return; } if (iid==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_IMEI2IID - input parameter iid is NULL \n"); #endif return; } // End debug information memset(iid, 0, NAS_ADDR_LEN); iid[0] = 0x03; iid[1] = 16*imei[0]+imei[1]; iid[2] = 16*imei[2]+imei[3]; iid[3] = 16*imei[4]+imei[5]; iid[4] = 16*imei[6]+imei[7]; iid[5] = 16*imei[8]+imei[9]; iid[6] = 16*imei[10]+imei[11]; iid[7] = 16*imei[12]+imei[13]; } //struct udphdr *nas_TOOL_get_udp4(struct iphdr *iph) //{ // return (struct udphdr *)((char *)iph+NAS_IPV4_SIZE); // to modify //} //--------------------------------------------------------------------------- char *nas_TOOL_get_udpmsg(struct udphdr *udph){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_GET_UDPMSG - begin \n"); #endif if (udph==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_GET_UDPMSG - input parameter udph is NULL \n"); #endif return NULL; } // End debug information return ((char *)udph+sizeof(struct udphdr)); } //--------------------------------------------------------------------------- // Compute the UDP checksum (the data size must be odd) uint16_t nas_TOOL_udpcksum(struct in6_addr *saddr, struct in6_addr *daddr, uint8_t proto, uint32_t udplen, void *data){ //--------------------------------------------------------------------------- uint32_t i; uint16_t *data16; uint32_t csum=0; // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_UDPCKSUM - begin \n"); #endif if (saddr==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_UDPCKSUM - input parameter saddr is NULL \n"); #endif return 0; } if (daddr==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_UDPCKSUM - input parameter daddr is NULL \n"); #endif return 0; } if (data==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_UDPCKSUM - input parameter data is NULL \n"); #endif return 0; } // End debug information data16=data; for (i=0; i<8; ++i) { csum+=ntohs(saddr->s6_addr16[i]); if (csum>0xffff) csum-=0xffff; } for (i=0; i<8; ++i) { csum+=ntohs(daddr->s6_addr16[i]); if (csum>0xffff) csum-=0xffff; } csum+=(udplen>>16); // udplen checksum if (csum>0xffff) csum -= 0xffff; csum+=udplen & 0xffff; if (csum>0xffff) csum -= 0xffff; csum+=proto; // protocol checksum if (csum>0xffff) csum-=0xffff; for (i = 0; 2*i < udplen; i++) { csum+=ntohs(data16[i]); if (csum>0xffff) csum-=0xffff; } return htons((uint16_t)(~csum)&0xffff); } //--------------------------------------------------------------------------- void print_TOOL_pk_udp(struct udphdr *udph){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("PRINT_TOOL_PK_UDP - begin \n"); #endif if (udph==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_PK_UDP - input parameter udph is NULL \n"); #endif return; } // End debug information if (udph!=NULL) { printk("UDP:\t source = %u, dest = %u, len = %u, check = %x\n", ntohs(udph->source), ntohs(udph->dest), ntohs(udph->len), udph->check); } } //--------------------------------------------------------------------------- void print_TOOL_pk_tcp(struct tcphdr *tcph){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("PRINT_TOOL_PK_TDP - begin \n"); #endif if (tcph==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_PK_TDP - input parameter tcph is NULL \n"); #endif return; } // End debug information if (tcph!=NULL) { printk("TCP:\t source = %u, dest = %u\n", tcph->source, tcph->dest); } } //--------------------------------------------------------------------------- void print_TOOL_pk_icmp6(struct icmp6hdr *icmph){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("PRINT_TOOL_PK_ICMP6 - begin \n"); #endif if (icmph==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_PK_ICMP6 - input parameter icmph is NULL \n"); #endif return; } // End debug information if (icmph!=NULL) { printk("ICMPv6:\t type= %d, code = %d\n", icmph->icmp6_type, icmph->icmp6_code); switch(icmph->icmp6_type) { case ICMPV6_DEST_UNREACH:printk("Destination unreachable\n");break; case ICMPV6_PKT_TOOBIG:printk("Packet too big\n");break; case ICMPV6_TIME_EXCEED:printk("Time exceeded\n");break; case ICMPV6_PARAMPROB:printk("Parameter problem\n");break; case ICMPV6_ECHO_REQUEST:printk("Echo request\n");break; case ICMPV6_ECHO_REPLY:printk("Echo reply\n");break; case ICMPV6_MGM_QUERY:printk("Multicast listener query\n");break; case ICMPV6_MGM_REPORT:printk("Multicast listener report\n");break; case ICMPV6_MGM_REDUCTION:printk("Multicast listener done\n");break; case NDISC_ROUTER_SOLICITATION:printk("Router solicitation\n");break; case NDISC_ROUTER_ADVERTISEMENT:printk("Router advertisment\n");break; case NDISC_NEIGHBOUR_SOLICITATION:printk("Neighbour solicitation\n");break; case NDISC_NEIGHBOUR_ADVERTISEMENT:printk("Neighbour advertisment\n");break; case NDISC_REDIRECT:printk("redirect message\n");break; } } } //--------------------------------------------------------------------------- void print_TOOL_pk_ipv6(struct ipv6hdr *iph){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("PRINT_TOOL_PK_IPv6 - begin \n"); #endif if (iph==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_PK_IPv6 - input parameter iph is NULL \n"); #endif return; } // End debug information if (iph!=NULL) { // char addr[NAS_INET6_ADDRSTRLEN]; printk("IP:\t version = %u, priority = %u, payload_len = %u\n", iph->version, iph->priority, ntohs(iph->payload_len)); printk("\t fl0 = %u, fl1 = %u, fl2 = %u\n",iph->flow_lbl[0],iph->flow_lbl[1],iph->flow_lbl[2]); printk("\t next header = %u, hop_limit = %u\n", iph->nexthdr, iph->hop_limit); // inet_ntop(AF_INET6, (void *)(&iph->saddr), addr, NAS_INET6_ADDRSTRLEN); // printk("\t saddr = %s",addr); // inet_ntop(AF_INET6, (void *)(&iph->daddr), addr, NAS_INET6_ADDRSTRLEN); // printk(", daddr = %s\n",addr); switch(iph->nexthdr) { case IPPROTO_UDP: print_TOOL_pk_udp((struct udphdr *)((char *)iph+sizeof(struct ipv6hdr))); break; case IPPROTO_TCP: print_TOOL_pk_tcp((struct tcphdr *)((char *)iph+sizeof(struct ipv6hdr))); break; case IPPROTO_ICMPV6: print_TOOL_pk_icmp6((struct icmp6hdr *)((char *)iph+sizeof(struct ipv6hdr))); break; case IPPROTO_IPV6: print_TOOL_pk_ipv6((struct ipv6hdr *)((char *)iph+sizeof(struct ipv6hdr))); break; default: printk("Unknown upper layer\n"); } } } //--------------------------------------------------------------------------- void print_TOOL_pk_ipv4(struct iphdr *iph){ //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("PRINT_TOOL_PK_IPv4 - begin \n"); #endif if (iph==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_PK_IPv4 - input parameter iph is NULL \n"); #endif return; } // End debug information if (iph!=NULL) { // char addr[NAS_INET_ADDRSTRLEN]; printk("IP:\t version = %u, IP length = %u\n", iph->version, iph->ihl); // inet_ntop(AF_INET, (void *)(&iph->saddr), addr, NAS_INET_ADDRSTRLEN); // printk("\t saddr = %s", addr); // inet_ntop(AF_INET, (void *)(&iph->saddr), addr, NAS_INET_ADDRSTRLEN); // printk("\t saddr = %s", addr); } } //--------------------------------------------------------------------------- void print_TOOL_pk_all(struct sk_buff *skb){ //--------------------------------------------------------------------------- printk("Skb:\t %p, len = %u\n", skb, skb->len); #ifdef KERNEL_VERSION_GREATER_THAN_2629 //navid: need to calculate the current used space: fixme? printk("Skb:\t available buf space = %u \n", skb->truesize); #else printk("Skb:\t available buf space = %u, cur used space = %u \n", skb->end-skb->head, skb->tail-skb->data); #endif switch (ntohs(skb->protocol)) { case ETH_P_IPV6: #ifdef KERNEL_VERSION_GREATER_THAN_2622 print_TOOL_pk_ipv6((struct ipv6hdr *)skb->network_header); #else print_TOOL_pk_ipv6(skb->nh.ipv6h); #endif break; case ETH_P_IP: #ifdef KERNEL_VERSION_GREATER_THAN_2622 print_TOOL_pk_ipv4((struct iphdr *)skb->network_header); #else print_TOOL_pk_ipv4(skb->nh.iph); #endif break; } } //--------------------------------------------------------------------------- /*int isdigit(char c) { switch(c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return 1; default: return 0; } }*/ /*int nas_TOOL_inet_pton4(char *src, uint32_t *dst) { uint32_t val; int n; uint8_t c; uint32_t parts[4]; c = *src; val=0; n=0 for (;;) { for (;;) { if (isdigit(c)) { val = (val * 10) + c - '0'; c = *++src; } else break; } if (c == '.') { if (n>4) return -1; parts[n]=val; c = *++src; ++n; } else break; } if ((c != '\0')||(n!=3)) return (0); if ((parts[0] | parts[1] | parts[2] | val) > 256) return (0); val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); if (dst) dst = htonl(val); return (1); }*/ //--------------------------------------------------------------------------- void print_TOOL_state(uint8_t state){ //--------------------------------------------------------------------------- // case NAS_STATE_IDLE:printk(" State NAS_STATE_IDLE\n");return; // case NAS_STATE_CONNECTED:printk(" State NAS_STATE_CONNECTED\n");return; // case NAS_STATE_ESTABLISHMENT_REQUEST:printk(" State NAS_STATE_ESTABLISHMENT_REQUEST\n");return; // case NAS_STATE_ESTABLISHMENT_FAILURE:printk(" State NAS_STATE_ESTABLISHMENT_FAILURE\n");return; // case NAS_STATE_RELEASE_FAILURE:printk(" State NAS_STATE_RELEASE_FAILURE\n");return; switch(state){ case NAS_IDLE:printk("NAS_IDLE\n");return; case NAS_CX_FACH:printk("NAS_CX_FACH\n");return; case NAS_CX_DCH:printk("NAS_CX_DCH\n");return; case NAS_CX_RECEIVED:printk("NAS_CX_RECEIVED\n");return; case NAS_CX_CONNECTING:printk("NAS_CX_CONNECTING\n");return; case NAS_CX_RELEASING:printk("NAS_CX_RELEASING\n");return; case NAS_CX_CONNECTING_FAILURE:printk("NAS_CX_CONNECTING_FAILURE\n");return; case NAS_CX_RELEASING_FAILURE:printk("NAS_CX_RELEASING_FAILURE\n");return; case NAS_RB_ESTABLISHING:printk("NAS_RB_ESTABLISHING\n");return; case NAS_RB_RELEASING:printk("NAS_RB_RELEASING\n");return; case NAS_RB_DCH:printk("NAS_RB_DCH\n");return; default: printk(" Unknown state\n"); } } //----------------------------------------------------------------------------- // Print the content of a buffer in hexadecimal void nas_tool_print_buffer(char * buffer,int length) { //----------------------------------------------------------------------------- int i; // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_PRINT_BUFFER - begin \n"); #endif if (buffer==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_TOOL_PRINT_BUFFER - input parameter buffer is NULL \n"); #endif return; } // End debug information printk("\nBuffer content: "); for (i=0;irab_id, rb->sapi, rb->qos); printk("state %d, retry %d, countimer %d\n",rb->state, rb->retry, rb->countimer); }; //----------------------------------------------------------------------------- void nas_print_classifier(struct classifier_entity *gc){ //----------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_TOOL printk("NAS_PRINT_GC_ENTITY - begin \n"); #endif if (gc==NULL){ #ifdef NAS_DEBUG_TOOL printk("NAS_PRINT_GC_ENTITY - input parameter gc is NULL \n"); #endif return; } // End debug information printk("\nClassifier content: classref %d, version %d, splen %d, dplen %d,\n", gc->classref, gc->version, gc->splen, gc->dplen); printk("protocol %d, sport %d, dport %d, rab_id %d\n", gc->protocol, gc->sport, gc->dport, gc->rab_id); if (gc->rb != NULL){ nas_print_rb_entity(gc->rb); } };