#ifdef __KERNEL__ #include <linux/module.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/udp.h> #endif #include <rtk_rg_sip.h> #include <rtk_rg_alg_tool.h> static int32 init_sip = 0; static uint8 *_rtl8651_l4_sip_alias_buf[1]; static uint16 o_port=0,i_port=0; int num_memcmp(void *src,void *dest,int num) { int r; char *pSrc=(char*)src; r=memcmp(src,dest,num); if(r!=0) return r; if((pSrc[num]>='0')&&(pSrc[num]<='9')) return -1; //ex: '192.168.1.1' hit '192.168.1.111' is not allow. return 0; } static char localip[16]; static int8 localip_len; static char globalip[16]; static int8 globalip_len; static char globalport[16]; static int8 globalport_len; static char localport[16]; static int8 localport_len; static char trueport[16]; static int8 trueport_len=0; static char temp_trueport[16]; static int8 temp_trueport_len=0; static char rtpport[16]; static int8 rtpport_len=0; //char controlport[16]; //int8 controlport_len=0; //char controlextport[16]; //int8 controlextport_len=0; static char remoteip[16]; static int8 remoteip_len; static char key[32]; static int8 key_len; static char keyword[32]; static int8 keyword_len; static char ipkey[32]; static int8 ipkey_len; static uint32 trueip=0; static char realip[32]; static int8 realip_len=0; static int8 old_cl_len=0; //old content-length len static int8 new_cl_len=0; //new content-length len //uint32 extIP; static uint16 extPort; static uint16 control_port = 0; //uint16 control_extport = 0; //uint16 rtcpPort = 0; static int8 SameSubnet = FALSE; //for inbound static char viakey[32]; static int8 viakey_len=0; static char rportkey[32]; static int8 rportkey_len; static int8 SameGw = TRUE; static char realrtpport[32]; static int8 realrtpport_len = 0; static char realport[32]; static int8 realport_len = 0; static uint32 truelocalip = 0; static uint16 trueport_num = 0; static int _rtk_rg_sip_process(int direct, unsigned char * pData, unsigned int dataLen,rtk_rg_alg_connection_t * pConn) { //int ret,newDelta=0; int ret; //ipaddr_t ipAddr,gwIPAddr; //unsigned short portNum,newPort; //unsigned int newLen,flowIdx; rtk_rg_pktHdr_t *pPktHdr; struct sk_buff *skb; //rtk_rg_naptEntry_t naptEntry; rtk_rg_upnpConnection_t upnpConn; pPktHdr = (rtk_rg_pktHdr_t *)pConn->pPktHdr; skb = (struct sk_buff *)pConn->skb; //if(direct==NAPT_DIRECTION_OUTBOUND) { int i,j,k; int32 size_delta=0; //for new packet struct iphdr *spip; struct udphdr *sudp; int8 *sptr, *newpacket; //for data flow mapt priority int index; rtk_rg_naptFilterAndQos_t napt_filter; // assigned new packet buffer ; use the latter part of _rtl8651_l4_sip_alias_buf newpacket = (int8 *)_rtl8651_l4_sip_alias_buf[0]; // copy out the mbuf data memcpy(newpacket,skb->data,(skb->len>_RTL8651_L4_MAX_SIP_ALIAS_BUF_SIZE)?_RTL8651_L4_MAX_SIP_ALIAS_BUF_SIZE:skb->len); //shift pointer to IP header newpacket+=pPktHdr->l3Offset; // Place string pointer and beginning of data spip=(struct iphdr*)newpacket; sudp=(struct udphdr *)((int8 *) spip + ((spip->ihl &0xf) << 2)); sptr=(int8 *)(sudp+1); sprintf(localip,"%u.%u.%u.%u",(pConn->tuple.internalIp.ip>>24)&0xff,(pConn->tuple.internalIp.ip>>16)&0xff,(pConn->tuple.internalIp.ip>>8)&0xff,(pConn->tuple.internalIp.ip)&0xff); localip_len=strlen(localip); sprintf(localport, "%u", (pConn->tuple.internalPort)&0xffff); localport_len = strlen(localport); sprintf(globalip,"%u.%u.%u.%u",(pConn->tuple.extIp.ip>>24)&0xff,(pConn->tuple.extIp.ip>>16)&0xff,(pConn->tuple.extIp.ip>>8)&0xff,(pConn->tuple.extIp.ip)&0xff); globalip_len=strlen(globalip); sprintf(globalport, "%u", (pConn->tuple.extPort)&0xffff); globalport_len = strlen(globalport); sprintf(remoteip,"%u.%u.%u.%u",(pConn->tuple.remoteIp.ip>>24)&0xff,(pConn->tuple.remoteIp.ip>>16)&0xff,(pConn->tuple.remoteIp.ip>>8)&0xff,(pConn->tuple.remoteIp.ip)&0xff); remoteip_len = strlen(remoteip); if(direct==NAPT_DIRECTION_OUTBOUND) { ALG("[SIP OUT] Begin: local=%s:%s global=%s:%s remote=%s\n",localip,localport,globalip,globalport,remoteip); } else { ALG("[SIP IN] Begin: local=%s:%s global=%s:%s remote=%s\n",localip,localport,globalip,globalport,remoteip); } sprintf(key,"\r\nContent-Length: "); key_len=18; /*get the rtp listening port*/ sprintf(keyword, "audio"); keyword_len = 5; /*for search the real ip which may send rtp pkt later*/ sprintf(ipkey, "IP4"); ipkey_len = 3; if(direct==NAPT_DIRECTION_INBOUND) { sprintf(viakey, "SIP/2.0/UDP"); viakey_len = strlen(viakey); sprintf(rportkey, "rport="); rportkey_len = 6; } for(i=0,j=0;i<dataLen;i++,j++) { if(pData[i]<0x20&&pData[i]!=0x0d&&pData[i]!=0x0a) return SUCCESS; //not sip packet if(i+4<=dataLen) { // search RTP Port number if(memcmp(&pData[i],"\r\nm=",4)==0) { int flag=0; if(direct==NAPT_DIRECTION_OUTBOUND) i_port=0; else o_port=0; for(k=i+4;k<dataLen;k++) { if(pData[k]==' ') { if(flag==0) flag=k; else { //printk("out- in_port=[%d] out_port=%d\n",i_port,o_port); //_rtl8651_addAlgQosUpnpMap(UPNP_PERSIST|UPNP_ALG_QOS, 0, 0, //tb->insideGlobalIpAddr, i_port, //tb->insideLocalIpAddr, i_port,RTL8651_ALG_SIP_IDX); //o_port=0; break; } } else if(flag!=0) { if(direct==NAPT_DIRECTION_OUTBOUND) i_port=(pData[k]-'0')+i_port*10; else o_port=(pData[k]-'0')+o_port*10; } } } else if((direct==NAPT_DIRECTION_INBOUND)&&(memcmp(&pData[i],viakey,viakey_len)==0)) { //search true port if (memcmp(&pData[i+viakey_len+1],globalip,globalip_len)==0) { for (k = i+viakey_len +globalip_len +2; k <dataLen; k++ ) { if((pData[k] >= '0') && (pData[k] <= '9')) { trueport_num=(pData[k]-'0')+trueport_num*10; } else break; } ALG("[SIP IN]trueport_num=%d\n",trueport_num); SameGw = TRUE; } //search remote ip else if(memcmp(&pData[i+viakey_len+1],remoteip,remoteip_len)!=0) { SameGw = FALSE; } } else if ((direct==NAPT_DIRECTION_INBOUND)&&((memcmp(&pData[i], ipkey, ipkey_len) ==0) && (memcmp(&pData[i + ipkey_len +1 ],globalip,globalip_len)!=0))) { // printk("not the same gateway\n"); SameGw = FALSE; } else if((direct==NAPT_DIRECTION_OUTBOUND)&&(memcmp(&pData[i], ipkey, ipkey_len)==0)) { uint16 temp=0; trueip=0; for(k= i+4; k<dataLen;k++) { if(pData[k] ==' ') { trueip = (trueip << 8) + temp; break; } else if (pData[k] == '.') { trueip = (trueip << 8) + temp; temp = 0; } else if (pData[k] >= '0' && pData[k] <= '9') { temp=(pData[k]-'0')+temp*10; if (temp > 255) temp = temp/10; } } } else if((direct==NAPT_DIRECTION_OUTBOUND)&&( num_memcmp(&pData[i], localip, localip_len) ==0 ) && (memcmp(&pData[i + localip_len + 1], localport, localport_len) != 0)) { int flag=0; control_port=0; for(k=i + localip_len;k<i + localip_len +6;k++) { if (pData[k] >= '0' && pData[k] <= '9') { flag = 1; } else flag = 0; if (flag ==1 ) control_port=(pData[k]-'0')+control_port*10; } if (control_port < 1024) control_port = 0; ALG("[SIP OUT]control port is %d\n", control_port); } // if (trueip != 0) // break; } } if((direct==NAPT_DIRECTION_OUTBOUND)&&(i_port !=0)) { extPort=_rtk_rg_extPort_get(0,i_port); //if(newPort==FAIL) return SUCCESS; //add UPnP connection here!! sprintf(trueport, "%u", (i_port)&0xffff); trueport_len = strlen(trueport); sprintf(temp_trueport, " %u", (i_port)&0xffff); temp_trueport_len = strlen(trueport)+1; sprintf(rtpport, "%u", (extPort)&0xffff); //control flow ext port rtpport_len = strlen(rtpport); //Add a one-shot UPnP flow for incoming connection to each L4 WAN upnpConn.is_tcp=pConn->tuple.isTcp; upnpConn.wan_intf_idx=pPktHdr->netifIdx; upnpConn.gateway_port=extPort; upnpConn.local_ip=pConn->tuple.internalIp.ip; upnpConn.local_port=i_port; upnpConn.limit_remote_ip=1; upnpConn.limit_remote_port=0; //can't restrict client using which port to connect upnpConn.remote_ip=pConn->tuple.remoteIp.ip; upnpConn.remote_port=0; upnpConn.type=UPNP_TYPE_ONESHOT; upnpConn.timeout=rg_db.algUserDefinedTimeout[RTK_RG_ALG_SIP_TCP]; //auto time out if the client do not connect by this WAN assert_ok((pf.rtk_rg_upnpConnection_add)(&upnpConn,&ret)); ALG("[SIP OUT]add UPnP connection i_port=%d(%s) extPort=%d ret=%d\n",i_port,trueport,extPort,ret); //data flow napt priority is followed control flow priority. if((pPktHdr->tagif & TCP_TAGIF)||(pPktHdr->tagif & UDP_TAGIF)){// only support by TCP or UDP (Layer4 packet). //check is outbound priority need to assigned if(rg_db.naptOut[pPktHdr->naptOutboundIndx].priValid==ENABLED){ bzero(&napt_filter,sizeof(napt_filter)); napt_filter.direction=RTK_RG_NAPT_FILTER_OUTBOUND; napt_filter.filter_fields = (L4_PROTOCAL|INGRESS_SIP|INGRESS_SPORT); if(pPktHdr->tagif & TCP_TAGIF) napt_filter.ingress_l4_protocal = 0x6; else if(pPktHdr->tagif & UDP_TAGIF) napt_filter.ingress_l4_protocal = 0x11; napt_filter.ingress_src_ipv4_addr = pConn->tuple.internalIp.ip; napt_filter.ingress_src_l4_port = i_port; napt_filter.action_fields = ASSIGN_NAPT_PRIORITY_BIT; napt_filter.assign_priority = rg_db.naptOut[pPktHdr->naptOutboundIndx].priValue;//follow control flow. napt_filter.ruleType = RTK_RG_NAPT_FILTER_ONE_SHOT; assert_ok((pf.rtk_rg_naptFilterAndQos_add)(&index,&napt_filter)); ALG("FTP ALG add outbound naptFilter[%d](L4_PROTOCAL=0x%x SIP=0x%x + sport=%d => priority=%d, one shot) for data flow (The priority is based on napt[%d])", index,napt_filter.ingress_l4_protocal,napt_filter.ingress_src_ipv4_addr,napt_filter.ingress_src_l4_port,napt_filter.assign_priority,pPktHdr->naptOutboundIndx); } //check is inbound priority need to assigned if(rg_db.naptIn[pPktHdr->naptrInboundIndx].priValid==ENABLED){ bzero(&napt_filter,sizeof(napt_filter)); napt_filter.direction=RTK_RG_NAPT_FILTER_INBOUND; napt_filter.filter_fields = (L4_PROTOCAL|INGRESS_DPORT|INGRESS_SIP); if(pPktHdr->tagif & TCP_TAGIF) napt_filter.ingress_l4_protocal = 0x6; else if(pPktHdr->tagif & UDP_TAGIF) napt_filter.ingress_l4_protocal = 0x11; napt_filter.ingress_dest_l4_port = extPort; napt_filter.ingress_src_ipv4_addr = pConn->tuple.remoteIp.ip; napt_filter.action_fields = ASSIGN_NAPT_PRIORITY_BIT; napt_filter.assign_priority = rg_db.naptIn[pPktHdr->naptrInboundIndx].priValue;//follow control flow. napt_filter.ruleType = RTK_RG_NAPT_FILTER_ONE_SHOT; assert_ok((pf.rtk_rg_naptFilterAndQos_add)(&index,&napt_filter)); ALG("FTP ALG add inbound naptFilter[%d](L4_PROTOCAL=0x%x SIP=0x%x + dport=%d => priority=%d, one shot) for data flow (The priority is based on naptr[%d])", index,napt_filter.ingress_l4_protocal,napt_filter.ingress_src_ipv4_addr,napt_filter.ingress_dest_l4_port,napt_filter.assign_priority,pPktHdr->naptrInboundIndx); } } } if(direct==NAPT_DIRECTION_INBOUND) { if(o_port!=0) { sprintf(rtpport, "%u", (o_port)&0xffff); //external RTP Port rtpport_len = strlen (rtpport); sprintf(realrtpport, "%u", (i_port)&0xffff); //local RTP Port realrtpport_len = strlen(realrtpport); ALG("[SIP IN] oport = %d\n", o_port); } if (trueport_num != 0) { //sip_tb = &entry; rtk_rg_lookupIdxReturn_t naptOutIdx; rtk_rg_fwdEngineReturn_t fwd_ret; ipaddr_t transIP; uint16 transPort; sprintf(realport, "%u", (trueport_num)&0xffff); realport_len = strlen (realport); naptOutIdx=_rtk_rg_naptTcpUdpInHashIndexLookup(0,pPktHdr->ipv4Sip,pPktHdr->sport,pConn->tuple.extIp.ip,trueport_num); fwd_ret = _rtk_rg_fwdEngine_connType_lookup(pPktHdr,&transIP,&transPort); if(fwd_ret==RG_FWDENGINE_RET_CONTINUE) { truelocalip = transIP; sprintf(realip,"%u.%u.%u.%u",(truelocalip>>24)&0xff,(truelocalip>>16)&0xff,(truelocalip>>8)&0xff,(truelocalip)&0xff); realip_len=strlen(realip); ALG("[SIP IN] trueip = %x\n", truelocalip); } else { ALG("[SIP IN] trueip not found!\n"); } } } //change content!! for(i=0,j=0;i<dataLen;i++,j++) { if((i+key_len<=dataLen)&&(memcmp(&pData[i],key,key_len)==0)) { //find "\r\nContent-Length: " int32 datalen=0; int32 flag=0; int32 datalen_stringlen=0; char tempStr[16]; int32 CntIpInMsgBody=0; int32 CntPortInMsgBody=0; int32 CntTrueIpInMsgbody=0; int32 CntRealIpInMsgBody=0; //for inbound int msg; memcpy(&sptr[j],key,key_len); j+=key_len; i+=key_len; for(k=i;((k<i+20)&&(k<dataLen));k++) { if((pData[k]>='0')&&(pData[k]<='9')) { datalen=pData[k]-'0'+datalen*10; flag = 1; datalen_stringlen = datalen_stringlen +1; } else { if (flag == 1) break; } } ALG("[SIP] Content-Length=%d datalen_stringlen=%d\n",datalen,datalen_stringlen); memcpy(&sptr[j], &pData[i], k -datalen_stringlen -i); j += k -datalen_stringlen -i; i += k -datalen_stringlen -i; old_cl_len=datalen_stringlen; i=k-1; msg=i+2; //find msg body for(k=i+2;k<=dataLen-4;k++) { if(memcmp(&pData[k],"\r\n\r\n",4)==0) { msg=k+4; break; } } if(direct==NAPT_DIRECTION_OUTBOUND) { // count how many ip in Message body for(k=msg;k<=dataLen-localip_len;k++) { if ((num_memcmp(&pData[k],localip,localip_len)==0) /*&& (memcmp(&pData[k - ipkey_len -1], ipkey, ipkey_len) !=0)*/) { CntIpInMsgBody++; } } for(k=msg;k<=dataLen-trueport_len;k++) { if(i_port != 0) { //sample rate format="/XXXXX", media port format=" XXXX". // to avoid these two fields have the same value. //if(num_memcmp(&pData[k],trueport,trueport_len)==0) if(num_memcmp(&pData[k],temp_trueport,temp_trueport_len)==0) { CntPortInMsgBody++; } } } if ((trueip!=0) && (SameSubnet == TRUE)) { for(k=msg;k<=dataLen-realip_len;k++) { if ((num_memcmp(&pData[k],realip,realip_len)==0) /*&& (memcmp(&pData[k - ipkey_len -1], ipkey, ipkey_len) !=0)*/) { CntTrueIpInMsgbody++; //printk("CntTrueIpInMsgbody = %d\n", CntTrueIpInMsgbody); } } } if(i_port != 0) new_cl_len=sprintf(tempStr,"%u",datalen+(CntIpInMsgBody*(globalip_len-localip_len)) + CntPortInMsgBody*(rtpport_len - trueport_len) + (CntTrueIpInMsgbody*(globalip_len - realip_len))); else new_cl_len=sprintf(tempStr,"%u",datalen+(CntIpInMsgBody*(globalip_len-localip_len)) + (CntTrueIpInMsgbody*(globalip_len - realip_len))); memcpy(&sptr[j],tempStr,new_cl_len); j+=(new_cl_len-1); ALG("[SIP OUT]CntIpInMsgBody = %d CntPortInMsgBody=%d, new_cl_len=%d\n", CntIpInMsgBody,CntPortInMsgBody,new_cl_len); } else //inbound { // count how many ip in Message body for(k=msg;k<=dataLen-globalip_len;k++) { if((num_memcmp(&pData[k],globalip,globalip_len)==0) && (memcmp(&pData[k - ipkey_len -1], ipkey, ipkey_len) !=0) ) { CntIpInMsgBody++; } } for(k=msg;k<=dataLen-globalip_len;k++) { if((num_memcmp(&pData[k],globalip,globalip_len)==0) && (memcmp(&pData[k - ipkey_len -1], ipkey, ipkey_len) ==0) && (truelocalip !=0)) { CntRealIpInMsgBody++; } } if(datalen==0) { new_cl_len=1; tempStr[0]='0'; tempStr[1]=0; ALG("[SIP OUT] content len=0, don't modify"); } else { if (SameGw == FALSE) new_cl_len=sprintf(tempStr,"%u",datalen+(CntIpInMsgBody*(localip_len-globalip_len))+ (CntRealIpInMsgBody*(realip_len-globalip_len))); else if ((o_port != 0) && (trueport_num != 0)) new_cl_len=sprintf(tempStr,"%u",datalen+(CntIpInMsgBody*(localip_len-globalip_len))+ (CntRealIpInMsgBody*(realip_len-globalip_len)) + (realrtpport_len-rtpport_len)); else new_cl_len=sprintf(tempStr,"%u",datalen + (CntIpInMsgBody*(localip_len-globalip_len))); } memcpy(&sptr[j],tempStr,new_cl_len); j+=(new_cl_len-1); } } else if((direct==NAPT_DIRECTION_OUTBOUND)&&(i+localip_len<=dataLen)&&(num_memcmp(&pData[i],localip,localip_len)==0) /*&& (memcmp(&pData[i - ipkey_len -1], ipkey, ipkey_len) !=0)*/) { memcpy(&sptr[j],globalip,globalip_len); i+=(localip_len-1); j+=(globalip_len-1); size_delta+=(globalip_len-localip_len); ALG("[SIP OUT] match local ip address = %s-->%s size_delta=%d\n",localip,globalip,size_delta); } else if((direct==NAPT_DIRECTION_OUTBOUND)&&(i+localport_len <= dataLen) && (num_memcmp(&pData[i], localport, localport_len) == 0) && (memcmp(&pData[i -localip_len -1], localip, localip_len) == 0)) { memcpy(&sptr[j], globalport, globalport_len); i+=(localport_len-1); j+=(globalport_len-1); size_delta += (globalport_len-localport_len); ALG("[SIP OUT] match local port & local ip address = %s-->%s size_delta=%d\n",localport,globalport,size_delta); } #if 0 else if((direct==NAPT_DIRECTION_OUTBOUND)&&(i+controlport_len <= dataLen) && (control_port != 0) && (num_memcmp(&pData[i], controlport, controlport_len) == 0) && (memcmp(&pData[i -localip_len -1], localip, localip_len) == 0)) { memcpy(&sptr[j], controlextport, controlextport_len); i+=(controlport_len-1); j+=(controlextport_len-1); size_delta += (controlextport_len-controlport_len); ALG("[SIP OUT] match control port & local ip address = c-port:%d-->c-extport:%d size_delta=%d dataLen=%d\n",control_port,controlextport,size_delta,dataLen); } #endif else if((direct==NAPT_DIRECTION_OUTBOUND)&&(i+trueport_len <= dataLen) && (num_memcmp(&pData[i-1], temp_trueport, temp_trueport_len) == 0) && (i_port != 0) /*&& ((memcmp(&pData[i -keyword_len -1], keyword, keyword_len) == 0))*/) { memcpy(&sptr[j], rtpport, rtpport_len); //printk("change rtp port\n"); i+=(trueport_len-1); j+=(rtpport_len-1); size_delta += (rtpport_len-trueport_len); ALG("[SIP OUT] match trueport = %s-->%s size_delta=%d\n",trueport,rtpport,size_delta); } else if((direct==NAPT_DIRECTION_OUTBOUND)&&(i+realip_len <= dataLen) && (num_memcmp(&pData[i], realip, realip_len) == 0) && (trueip != 0) && (SameSubnet == TRUE) && (memcmp(&pData[i - ipkey_len -1], ipkey, ipkey_len) ==0)) { memcpy(&sptr[j], globalip, globalip_len); i+=(realip_len-1); j+=(globalip_len-1); size_delta += (globalip_len-realip_len); ALG("[SIP OUT] match real ip = %s-->%s size_delta=%d\n",realip,globalip,size_delta); //printk("modify true ip\n"); } else if((direct==NAPT_DIRECTION_INBOUND)&&((i+globalip_len<=dataLen))&&(num_memcmp(&pData[i],globalip,globalip_len)==0) &&(memcmp(&pData[i - ipkey_len -1], ipkey, ipkey_len) !=0) ) { ALG("[SIP IN] match ip in address(without [IP4]) = %s-->%s\n",globalip,localip); memcpy(&sptr[j],localip,localip_len); i+=(globalip_len-1); j+=(localip_len-1); size_delta+=(localip_len-globalip_len); } else if((direct==NAPT_DIRECTION_INBOUND)&&((i+globalip_len<=dataLen))&&(num_memcmp(&pData[i],globalip,globalip_len)==0) &&(memcmp(&pData[i- ipkey_len -1], ipkey, ipkey_len) ==0) && (truelocalip !=0)) { ALG("[SIP IN] match ip in address(with [IP4]) = %s-->%s\n",globalip,realip); memcpy(&sptr[j],realip,realip_len); i+=(globalip_len-1); j+=(realip_len-1); size_delta+=(realip_len-globalip_len); } else if((direct==NAPT_DIRECTION_INBOUND)&&(i+globalport_len <= dataLen) && (num_memcmp(&pData[i], globalport, globalport_len) == 0)) { ALG("[SIP IN] match global port = %s-->%s\n",globalport,localport); memcpy(&sptr[j], localport, localport_len); i+=(globalport_len-1); j+=(localport_len-1); size_delta += (localport_len-globalport_len); } else if((direct==NAPT_DIRECTION_INBOUND)&&(i+realport_len <= dataLen) && (num_memcmp(&pData[i], realport, realport_len) == 0) && (trueport_num != 0) && ((memcmp(&pData[i-rportkey_len], rportkey, rportkey_len) != 0))) { ALG("[SIP IN] find real port by [rport=] = %s-->%s\n",realport,localport); memcpy(&sptr[j], localport, localport_len); i+=(realport_len-1); j+=(localport_len-1); size_delta += (localport_len-realport_len); } else if((direct==NAPT_DIRECTION_INBOUND)&&(i+rtpport_len <= dataLen) && (num_memcmp(&pData[i], rtpport, rtpport_len) == 0) && (o_port != 0) && ((memcmp(&pData[i -keyword_len -1], keyword, keyword_len) == 0)) && (SameGw == TRUE) && (trueport_num != 0)) { ALG("[SIP IN] match RTP port by [audio] = %s-->%s\n",rtpport,realrtpport); memcpy(&sptr[j], realrtpport, realrtpport_len); //printk("change rtp port\n"); i+=(rtpport_len-1); j+=(realrtpport_len-1); size_delta += (realrtpport_len-rtpport_len); } else { sptr[j]=pData[i]; } } ALG("size_delta=%d new_cl_len=%d old_cl_len=%d\n",size_delta,new_cl_len,old_cl_len); spip->tot_len = htons(ntohs(spip->tot_len)+size_delta+new_cl_len-old_cl_len); sudp->len = htons(ntohs(sudp->len)+size_delta+new_cl_len-old_cl_len); skb_put(skb, size_delta); memcpy(&skb->data[pPktHdr->l3Offset],(void*)spip,ntohs(spip->tot_len)); //skb->len=pPktHdr->l3Offset+ntohs(spip->tot_len); if(pPktHdr->egressTagif&PPPOE_TAGIF) { // set pppoe length = IP total length + 2 skb->data[pPktHdr->l3Offset-4]=htons(ntohs(spip->tot_len)+2)>>8; skb->data[pPktHdr->l3Offset-3]=htons(ntohs(spip->tot_len)+2)&0xff; //update l3 length pPktHdr->l3Len = ntohs(spip->tot_len); *pPktHdr->pL3Len = spip->tot_len; #if defined(CONFIG_RTL9600_SERIES) //20160331LUKE: checksum by sw offload //re-cal l3 checksum *pPktHdr->pIpv4Checksum=0; *pPktHdr->pIpv4Checksum=htons(inet_chksum(skb->data+pPktHdr->l3Offset,pPktHdr->l4Offset-pPktHdr->l3Offset)); //re-cal l4 checksum *pPktHdr->pL4Checksum=0; *pPktHdr->pL4Checksum=htons(inet_chksum_pseudo(skb->data+pPktHdr->l4Offset,pPktHdr->l3Offset+(*pPktHdr->pL3Len)-pPktHdr->l4Offset,ntohl(*pPktHdr->pIpv4Sip),ntohl(*pPktHdr->pIpv4Dip),pPktHdr->ipProtocol)); #endif } //memDump(skb->data,skb->len,"new sip out"); //checksum re-calulate by HW //*pPktHdr->pL4Checksum=0; //*pPktHdr->pL4Checksum=htons(inet_chksum_pseudo(skb->data+pPktHdr->l4Offset,pPktHdr->l3Offset+pPktHdr->l3Len-pPktHdr->l4Offset,ntohl(*pPktHdr->pIpv4Sip),ntohl(*pPktHdr->pIpv4Dip),pPktHdr->ipProtocol)); } return 1; } int _rtk_rg_sip_handler(int direct, int after, unsigned char *pSkb,unsigned char *pPktInfo, unsigned char * pConnInfo) { int ret = SUCCESS; #ifdef __KERNEL__ unsigned char * pData, *pAppData; unsigned int appLen=0,dataOff=0; rtk_rg_pktHdr_t *pPktHdr; struct sk_buff *skb; rtk_rg_alg_connection_t * pConn; pPktHdr = (rtk_rg_pktHdr_t *)pPktInfo; pConn = (rtk_rg_alg_connection_t *)pConnInfo; skb= (struct sk_buff *)pSkb; pData=skb->data; if(pPktHdr->tagif&TCP_TAGIF) dataOff = pPktHdr->l4Offset + pPktHdr->headerLen; else dataOff = pPktHdr->l4Offset + 8; /*udp header length is 8 bytes*/ appLen = skb->len - dataOff; pAppData = pData + dataOff; //do nothing before napt modification if(after == 0) { if(direct==NAPT_DIRECTION_INBOUND) { if(pConn->tuple.isIp6==0) { pConn->tuple.extIp.ip = ntohl(*pPktHdr->pIpv4Dip); pConn->tuple.extPort = ntohs(*pPktHdr->pDport); } } return SUCCESS; } //extIP= egress gateway ip if(direct==NAPT_DIRECTION_OUTBOUND) { if(pConn->tuple.isIp6==0) { pConn->tuple.extIp.ip = ntohl(*pPktHdr->pIpv4Sip); pConn->tuple.extPort = ntohs(*pPktHdr->pSport); } } pConn->skb=pSkb; pConn->pPktHdr=pPktInfo; ret = _rtk_rg_sip_process(direct, pAppData, appLen, pConn); if(ret < 1) return FAIL; #endif return ret; } rtk_rg_fwdEngineAlgReturn_t rtk_rg_algRegFunc_sip(int direct, int after, unsigned char *pSkb,unsigned char *pPktInfo) { //Attention: caller function needs to make sure it needs to do napt modification //ipv6 address and port doesn't need to do napt modification now #ifdef __KERNEL__ int ret; rtk_rg_pktHdr_t *pPktHdr; rtk_rg_alg_connection_t * pConn; rtk_rg_alg_tuple_t tuple; pPktHdr = (rtk_rg_pktHdr_t *)pPktInfo; memset(&tuple, 0, sizeof(rtk_rg_alg_tuple_t)); if(after==0) { //Pre function if(direct==NAPT_DIRECTION_OUTBOUND) { _rtk_rg_alg_init_tuple(direct, after, pPktHdr, &tuple); pConn = _rtk_rg_alg_connection_find(&tuple); if(pConn == NULL) { pConn = _rtk_rg_alg_connection_add(&tuple); } //else //_rtk_rg_sync_tcp_ack_seq(direct, pPktHdr, pConn); } } else //after=1 { if(direct==NAPT_DIRECTION_OUTBOUND) { _rtk_rg_alg_init_tuple(direct, after, pPktHdr, &tuple); pConn = _rtk_rg_alg_connection_find(&tuple); if(pConn == NULL) return RG_FWDENGINE_ALG_RET_FAIL; ret = _rtk_rg_sip_handler(direct, after, pSkb, pPktInfo, (unsigned char *)pConn); } else { //Attention, pPktHdr->ipv4Dip is not the original external ip after napt modification, it is the internal ip _rtk_rg_alg_init_tuple(direct, after, pPktHdr, &tuple); pConn = _rtk_rg_alg_connection_find(&tuple); if(pConn == NULL) return RG_FWDENGINE_ALG_RET_FAIL; ret = _rtk_rg_sip_handler(direct, after, pSkb, pPktInfo, (unsigned char *)pConn); //_rtk_rg_sync_tcp_ack_seq(direct, pPktHdr, pConn); } } #endif return RG_FWDENGINE_ALG_RET_SUCCESS; } #ifdef __KERNEL__ static int __init init(void) { /* malloc global variable */ if(init_sip) return SUCCESS; _rtl8651_l4_sip_alias_buf[0] = (uint8 *)rtk_rg_malloc(_RTL8651_L4_MAX_SIP_ALIAS_BUF_SIZE); //assert(_rtl8651_l4_sip_alias_buf[0]); init_sip = 1; return SUCCESS; } static void __exit exit(void) { } module_init(init); module_exit(exit); #endif