//--------------------------------------------------------------------------- void print_TOOL_pk_ipv6(struct ipv6hdr *iph) { //--------------------------------------------------------------------------- // Start debug information #ifdef OAI_NW_DRV_DEBUG_TOOL printk("PRINT_TOOL_PK_IPv6 - begin \n"); #endif if (iph==NULL) { #ifdef OAI_NW_DRV_DEBUG_TOOL printk("OAI_NW_DRV_TOOL_PK_IPv6 - input parameter iph is NULL \n"); #endif return; } // End debug information if (iph!=NULL) { // char addr[OAI_NW_DRV_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, OAI_NW_DRV_INET6_ADDRSTRLEN); // printk("\t saddr = %s",addr); // inet_ntop(AF_INET6, (void *)(&iph->daddr), addr, OAI_NW_DRV_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"); } } }
//--------------------------------------------------------------------------- // Search the entity with the IPv6 address 'addr' struct cx_entity *nas_CLASS_cx6(struct sk_buff *skb, unsigned char dscp, struct nas_priv *gpriv, int inst, unsigned char *cx_searcher){ //--------------------------------------------------------------------------- unsigned char cxi; unsigned int *addr,*dst; struct cx_entity *default_ip=NULL; struct classifier_entity *p=NULL; #ifdef KERNEL_VERSION_GREATER_THAN_2630 if (skb->_skb_dst!=0) { #else if (skb->dst!=NULL) { #endif for (cxi=*cx_searcher; cxi<NAS_CX_MAX; cxi++) { (*cx_searcher)++; p = gpriv->cx[cxi].sclassifier[dscp]; while (p!=NULL) { if (p->version == 6) { // verify that this is an IPv4 rule if ((addr = (unsigned int *)(&(p->daddr.ipv6)))== NULL) { printk("nas_CLASS_cx6: addr is null \n"); p = p->next; continue; } #ifdef NAS_DEBUG_CLASS printk("cx %d : %X,%X.%X,%X\n",cxi,addr[0],addr[1],addr[2],addr[3]); #endif //NAS_DEBUG_CLASS #ifdef KERNEL_VERSION_GREATER_THAN_2630 if ((dst = (unsigned int*)&(((struct rt6_info *)(skb->_skb_dst))->rt6i_gateway)) == 0){ #else if ((dst = (unsigned int*)&(((struct rt6_info *)(skb->dst))->rt6i_gateway)) == NULL){ #endif printk("nas_CLASS_cx6: dst addr is null \n"); p = p->next; continue; } if ((addr[0] == dst[0]) && (addr[1] == dst[1]) && (addr[2] == dst[2]) && (addr[3] == dst[3])) { //#ifdef NAS_DEBUG_CLASS printk("nas_CLASS_cx6: found cx %d: %X.%X.%X.%X\n",cxi, dst[0], dst[1], dst[2], dst[3]); //#endif //NAS_DEBUG_CLASS return gpriv->cx+cxi; } /* else if ((addr[0]==NAS_DEFAULT_IPV6_ADDR0) && (addr[1]==NAS_DEFAULT_IPV6_ADDR1) && (addr[2]==NAS_DEFAULT_IPV6_ADDR2) && (addr[3]==NAS_DEFAULT_IPV6_ADDR3)) default_ip = gpriv->cx+cxi; */ } // Go to next classifier entry for connection p = p->next; } } } printk("nas_CLASS_cx6 NOT FOUND: %X.%X.%X.%X\n", dst[0], dst[1], dst[2], dst[3]); return default_ip; } //--------------------------------------------------------------------------- // Search the entity with the IPv4 address 'addr' struct cx_entity *nas_CLASS_cx4(struct sk_buff *skb, unsigned char dscp, struct nas_priv *gpriv, int inst, unsigned char *cx_searcher){ //--------------------------------------------------------------------------- unsigned char cxi; unsigned char *addr; struct cx_entity *default_ip=NULL; struct classifier_entity *p=NULL; // if (inst >0) // return(gpriv->cx); //dump to clusterhead #ifdef NAS_DEBUG_CLASS #ifdef KERNEL_VERSION_GREATER_THAN_2630 addr = (char *)&((((struct rtable *)(skb->_skb_dst))->rt_gateway)); #else addr = (char *)&((((struct rtable *)(skb->dst))->rt_gateway)); #endif if (addr) printk("[NAS][CLASS][IPv4] Searching for %d.%d.%d.%d\n",addr[0],addr[1],addr[2],addr[3]); #endif #ifdef KERNEL_VERSION_GREATER_THAN_2630 if (skb->_skb_dst!=0) { #else if (skb->dst!=NULL) { #endif for (cxi=*cx_searcher; cxi<NAS_CX_MAX; ++cxi) { (*cx_searcher)++; p = gpriv->cx[cxi].sclassifier[dscp]; while (p!=NULL) { if (p->version == 4) { // verify that this is an IPv4 rule #ifdef NAS_DEBUG_CLASS addr = (char *)(&(p->daddr.ipv4)); printk("cx %d : %d.%d.%d.%d\n",cxi,addr[0],addr[1],addr[2],addr[3]); #ifdef KERNEL_VERSION_GREATER_THAN_2630 addr = (char *)&(((struct rtable *)(skb->_skb_dst))->rt_gateway); #else addr = (char *)&(((struct rtable *)(skb->dst))->rt_gateway); #endif printk("rt_gateway : %d.%d.%d.%d\n",addr[0],addr[1],addr[2],addr[3]); #endif //NAS_DEBUG_CLASS #ifdef KERNEL_VERSION_GREATER_THAN_2630 if ((p->daddr.ipv4)== (((((struct rtable *)(skb->_skb_dst))->rt_gateway)))){ #else if ((p->daddr.ipv4)== (((((struct rtable *)(skb->dst))->rt_gateway)))){ #endif addr = (char *)(&(p->daddr.ipv4)); #ifdef NAS_DEBUG_CLASS printk("found cx %d: %d.%d.%d.%d\n",cxi, addr[0], addr[1], addr[2], addr[3]); #endif //NAS_DEBUG_CLASS return gpriv->cx+cxi; } /* else if (gpriv->cx[cxi].sclassifier[dscp]->daddr.ipv4==NAS_DEFAULT_IPV4_ADDR) { #ifdef NAS_DEBUG_CLASS printk("found default_ip rule\n"); #endif //NAS_DEBUG_CLASS default_ip = gpriv->cx+cxi; } */ } // goto to next classification rule for the connection p = p->next; } } } return default_ip; } #ifdef MPLS //--------------------------------------------------------------------------- // Search the entity with the mpls label and given exp struct cx_entity *nas_CLASS_MPLS(struct sk_buff *skb, unsigned char exp, struct nas_priv *gpriv, int inst, unsigned char *cx_searcher){ //--------------------------------------------------------------------------- unsigned char cxi; struct cx_entity *default_label=NULL; struct classifier_entity *p=NULL; // if (inst >0) // return(gpriv->cx); //dump to clusterhead #ifdef NAS_DEBUG_CLASS printk("[NAS][CLASS][MPLS] Searching for label %d\n",MPLSCB(skb)->label); #endif for (cxi=*cx_searcher; cxi<NAS_CX_MAX; ++cxi) { (*cx_searcher)++; p = gpriv->cx[cxi].sclassifier[exp]; while (p!=NULL) { if (p->version == NAS_MPLS_VERSION_CODE) { // verify that this is an MPLS rule #ifdef NAS_DEBUG_CLASS printk("cx %d : label %d\n",cxi,p->daddr.mpls_label); #endif //NAS_DEBUG_CLASS if (p->daddr.mpls_label==MPLSCB(skb)->label){ #ifdef NAS_DEBUG_CLASS printk("found cx %d: label %d, RB %d\n",cxi, MPLSCB(skb)->label, p->rab_id); #endif //NAS_DEBUG_CLASS return gpriv->cx+cxi; } /* else if (gpriv->cx[cxi].sclassifier[dscp]->daddr.ipv4==NAS_DEFAULT_IPV4_ADDR) { #ifdef NAS_DEBUG_CLASS printk("found default_ip rule\n"); #endif //NAS_DEBUG_CLASS default_ip = gpriv->cx+cxi; } */ } // goto to next classification rule for the connection p = p->next; } } return default_label; } #endif //--------------------------------------------------------------------------- // Search the sending function void nas_CLASS_send(struct sk_buff *skb,int inst){ //--------------------------------------------------------------------------- struct classifier_entity *p, *sp; u8 *protocolh,version; u8 protocol, dscp, exp,label; u16 classref; struct cx_entity *cx; unsigned int i; unsigned int router_adv = 0; struct net_device *dev=nasdev[inst]; struct nas_priv *gpriv=netdev_priv(dev); unsigned char cx_searcher,no_connection=1; #ifdef NAS_DEBUG_CLASS printk("NAS_CLASS_SEND: begin - inst %d\n",inst); #endif if (skb==NULL){ #ifdef NAS_DEBUG_SEND printk("NAS_CLASS_SEND - input parameter skb is NULL \n"); #endif return; } #ifdef NAS_DEBUG_SEND printk("[NAS][CLASS][SEND] Got packet from kernel:\n"); for (i=0;i<256;i++) printk("%2x ",((unsigned char *)skb->data)[i]); printk("\n"); #endif // find all connections related to socket cx_searcher = 0; no_connection = 1; //while (cx_searcher<NAS_CX_MAX) { cx = NULL; // Address classification switch (ntohs(skb->protocol)) { case ETH_P_IPV6: version = 6; protocolh=nas_TOOL_get_protocol6( #ifdef KERNEL_VERSION_GREATER_THAN_2622 (struct ipv6hdr *)(skb_network_header(skb)), #else skb->nh.ipv6h, #endif &protocol); dscp=nas_TOOL_get_dscp6( #ifdef KERNEL_VERSION_GREATER_THAN_2622 (struct ipv6hdr *)(skb_network_header(skb)) #else skb->nh.ipv6h #endif ); #ifdef NAS_DEBUG_CLASS printk("NAS_CLASS_SEND: %p %d %p %d %p \n",skb, dscp, gpriv, inst, &cx_searcher); #endif cx=nas_CLASS_cx6(skb,dscp,gpriv,inst,&cx_searcher); #ifdef NAS_DEBUG_CLASS printk("NAS_CLASS_SEND: Got IPv6 packet, dscp = %d\n",dscp); #endif break; case ETH_P_IP: #ifdef KERNEL_VERSION_GREATER_THAN_2622 dscp=nas_TOOL_get_dscp4((struct iphdr *)(skb_network_header(skb))); #else dscp=nas_TOOL_get_dscp4(skb->nh.iph); #endif cx=nas_CLASS_cx4(skb,dscp,gpriv,inst,&cx_searcher); protocolh=nas_TOOL_get_protocol4( #ifdef KERNEL_VERSION_GREATER_THAN_2622 (struct iphdr *)(skb_network_header(skb)), #else skb->nh.iph, #endif &protocol); #ifdef NAS_DEBUG_CLASS printk("NAS_CLASS_SEND: Got IPv4 packet (%x), dscp = %d, cx = %x\n",ntohs(skb->protocol),dscp,cx); #endif version = 4; break; #ifdef MPLS case ETH_P_MPLS_UC: cx=nas_CLASS_MPLS(skb,MPLSCB(skb)->exp,gpriv,inst,&cx_searcher); #ifdef NAS_DEBUG_CLASS printk("NAS_CLASS_SEND: Got MPLS unicast packet, exp = %d, label = %d, cx = %x\n",MPLSCB(skb)->exp,MPLSCB(skb)->label,cx); #endif dscp = MPLSCB(skb)->exp; version = NAS_MPLS_VERSION_CODE; protocol = version; break; #endif default: printk("NAS_CLASS_SEND: Unknown protocol\n"); version = 0; return; } // If a valid connection for the DSCP/EXP with destination address // is found scan all protocol-based classification rules if (cx) { classref=0; sp=NULL; #ifdef NAS_DEBUG_CLASS printk("[NAS][CLASSIFIER] DSCP/EXP %d : looking for classifier entry\n",dscp); #endif for (p=cx->sclassifier[dscp]; p!=NULL; p=p->next) { #ifdef NAS_DEBUG_CLASS printk("[NAS][CLASSIFIER] DSCP %d p->classref=%d,p->protocol=%d,p->version=%d\n",dscp,p->classref,p->protocol,p->version); #endif // Check if transport protocol/message match /* if ((p->protocol == protocol)) if ((protocol == NAS_PROTOCOL_ICMP6) && (version == 6)) if (p->protocol_message_type == (p->protocol_message_type )) { printk("[GRAAL][CLASSIFIER] Router advertisement\n"); } */ // normal rule checks that network protocol version matches if (p->version == version) { sp=p; classref=sp->classref; break; } } if (sp!=NULL) { #ifdef NAS_DEBUG_CLASS char sfct[10], sprotocol[10]; if (sp->fct==nas_COMMON_QOS_send) strcpy(sfct, "qos"); if (sp->fct==nas_CTL_send) strcpy(sfct, "ctl"); if (sp->fct==nas_COMMON_del_send) strcpy(sfct, "del"); if (sp->fct==nas_mesh_DC_send_sig_data_request) strcpy(sfct, "dc"); 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"); print_TOOL_pk_icmp6((struct icmp6hdr*)protocolh);break; #ifdef MPLS case NAS_MPLS_VERSION_CODE:strcpy(sprotocol,"mpls");break; #endif } printk("NAS_CLASS_SEND: (dscp %u, %s) received, (classref %u, fct %s, rab_id %u) classifier rule\n", dscp, sprotocol, sp->classref, sfct, sp->rab_id); #endif sp->fct(skb, cx, sp,inst); } // if classifier entry match found else { printk("NAS_CLASS_SEND: no corresponding item in the classifier, so the message is dropped\n"); // nas_COMMON_del_send(skb, cx, NULL,inst); } no_connection = 0; } // if connection found #ifdef NAS_DEBUG_CLASS if (no_connection == 1) printk("NAS_CLASS_SEND: no corresponding connection, so the message is dropped\n"); #endif NAS_DEBUG_CLASS // } // while loop over connections #ifdef NAS_DEBUG_CLASS printk("NAS_CLASS_SEND: end\n"); #endif }