//--------------------------------------------------------------------------- void nasmt_TOOL_pk_ipv6(struct ipv6hdr *iph){ //--------------------------------------------------------------------------- // Start debug information #ifdef GRAAL_DEBUG_TOOL printk("nasmt_TOOL_pk_ipv6 - begin \n"); #endif if (iph==NULL){ printk("nasmt_TOOL_pk_ipv6 - input parameter iph is NULL \n"); return; } // End debug information if (iph!=NULL) { // char addr[GRAAL_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, GRAAL_INET6_ADDRSTRLEN); // printk("\t saddr = %s",addr); // inet_ntop(AF_INET6, (void *)(&iph->daddr), addr, GRAAL_INET6_ADDRSTRLEN); // printk(", daddr = %s\n",addr); switch(iph->nexthdr) { case IPPROTO_UDP: nasmt_TOOL_pk_udp((struct udphdr *)((char *)iph+sizeof(struct ipv6hdr))); break; case IPPROTO_TCP: nasmt_TOOL_pk_tcp((struct tcphdr *)((char *)iph+sizeof(struct ipv6hdr))); break; case IPPROTO_ICMPV6: nasmt_TOOL_pk_icmp6((struct icmp6hdr *)((char *)iph+sizeof(struct ipv6hdr))); break; case IPPROTO_IPV6: nasmt_TOOL_pk_ipv6((struct ipv6hdr *)((char *)iph+sizeof(struct ipv6hdr))); break; default: printk("nasmt_TOOL_pk_ipv6 - Unknown upper layer\n"); } } }
//--------------------------------------------------------------------------- // Search the sending function for IP Packet void nasmt_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; #ifdef NAS_DEBUG_CLASS char sfct[10], sprotocol[10]; #endif struct net_device *dev = gdev; unsigned char cx_index,no_connection; int addr_type; 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("nasmt_CLASS_send: begin -\n"); #endif if (skb==NULL) { printk("nasmt_CLASS_send - input parameter skb is NULL \n"); return; } //*** #ifdef NAS_DEBUG_SEND printk("nasmt_CLASS_send - Received IP packet to transmit:"); if ((skb->data) != NULL) { if (skb->len<100) nasmt_TOOL_print_buffer(skb->data,skb->len); else nasmt_TOOL_print_buffer(skb->data,100); } #endif //*** // find all connections related to socket cx_index = 0; no_connection = 1; cx = NULL; #ifdef NAS_DEBUG_CLASS printk("nasmt_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 printk("nasmt_CLASS_send : skb->protocol : IPv6 \n"); #endif version = NAS_VERSION_6; addr_type = NAS_IPV6_ADDR_UNKNOWN; protocolh = nasmt_TOOL_get_protocol6(ipv6_hdr(skb), &protocol); dscp = nasmt_TOOL_get_dscp6 (ipv6_hdr(skb)); cx = nasmt_CLASS_cx6 (skb, dscp, &addr_type, &cx_index); #ifdef NAS_DEBUG_CLASS printk("nasmt_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: pclassifier=(&gpriv->cx[0])->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 nasmt_create_mask_ipv6_addr(&masked6_addr, pclassifier->dplen); if (IN6_ARE_ADDR_MASKED_EQUAL(&pclassifier->daddr.ipv6, &ipv6_hdr(skb)->daddr, &masked6_addr)) { // then force dscp cx = &gpriv->cx[0]; #ifdef NAS_DEBUG_CLASS printk("nasmt_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[0]; #ifdef NAS_DEBUG_CLASS printk("nasmt_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; // should have found a valid classification rule case NAS_IPV6_ADDR_UNKNOWN: default: printk("nasmt_CLASS_send: No corresponding address type\n"); } } break; case ETH_P_ARP: #ifdef NAS_DEBUG_CLASS printk("nasmt_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("nasmt_CLASS_send: ARP PACKET WRONG ADDR LEN or WRONG ARP HEADER TYPE\n"); break; } } else { printk("nasmt_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("nasmt_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("nasmt_CLASS_send: ARP DEST IP transport IP = %d.%d.%d.%d\n",NIPADDR(tip)); #endif pclassifier=(&gpriv->cx[0])->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 nasmt_create_mask_ipv4_addr(&masked_addr, pclassifier->dplen); #ifdef NAS_DEBUG_CLASS printk("nasmt_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[0]; #ifdef NAS_DEBUG_CLASS printk("nasmt_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[0]; #ifdef NAS_DEBUG_CLASS printk("nasmt_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 printk("nasmt_CLASS_send : skb->protocol : IPv4 \n"); #endif version = NAS_VERSION_4; addr_type = NAS_IPV4_ADDR_UNKNOWN; dscp = nasmt_TOOL_get_dscp4((struct iphdr *)(skb_network_header(skb))); cx = nasmt_CLASS_cx4(skb, dscp, &addr_type, &cx_index); protocolh = nasmt_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: pclassifier=(&gpriv->cx[0])->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 nasmt_create_mask_ipv4_addr(&masked_addr, pclassifier->dplen); #ifdef NAS_DEBUG_CLASS printk("nasmt_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[0]; #ifdef NAS_DEBUG_CLASS printk("nasmt_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[0]; #ifdef NAS_DEBUG_CLASS printk("nasmt_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("nasmt_CLASS_send: No corresponding address type\n"); } } #ifdef NAS_DEBUG_CLASS //printk("nasmt_CLASS_send: ETH_P_IP Received IPv4 packet (%02X), dscp = %d, cx = %08X\n",ntohs(skb->protocol),dscp,cx); if (cx) printk("nasmt_CLASS_send: ETH_P_IP Received IPv4 packet (%02X), dscp = %d, cx = %d\n",ntohs(skb->protocol),dscp,cx->lcr); else printk("nasmt_CLASS_send: ETH_P_IP Received IPv4 packet (%02X), dscp = %d, No valid connection\n",ntohs(skb->protocol),dscp); #endif break; default: printk("nasmt_CLASS_send: Unknown IP version protocol\n"); version = 0; return; } #ifdef NAS_DEBUG_SEND_DETAIL printk("nasmt_CLASS_send: [before if (cx != NULL)]\n"); #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("nasmt_CLASS_send: UE not connected, in state %d. Packet is dropped\n",cx->state); #endif return; } #ifdef NAS_DEBUG_CLASS printk("nasmt_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 printk("nasmt_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("nasmt_CLASS_send: IP version are equals\n"); sp=pclassifier; classref=sp->classref; #ifdef NAS_DEBUG_SEND_DETAIL printk("nasmt_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==nasmt_COMMON_QOS_send) strcpy(sfct, "data xfer"); if (sp->fct==nasmt_CTL_send) strcpy(sfct, "iocontrol"); if (sp->fct==nasmt_COMMON_del_send) strcpy(sfct, "delete"); if (sp->fct==nasmt_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"); nasmt_TOOL_pk_icmp6((struct icmp6hdr*)protocolh); break; default: strcpy(sprotocol, "other L4"); break; } printk("nasmt_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\nnasmt_CLASS_send: ERROR : CLASSIFIER FUNCTION IS NULL\n\n"); } no_connection = 0; // end : if classifier entry match found } else { printk("nasmt_CLASS_send: no corresponding item in the classifier list, so the message is dropped\n"); printk("nasmt_CLASS_send: packet parameters: dscp %u, %s\n", dscp, sprotocol); nasmt_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("nasmt_CLASS_send: no corresponding connection, so the message is dropped\n"); } printk("nasmt_CLASS_send: end\n"); #endif }