/* // Copyright (c) 2017 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. */ /*Sriramajeyam*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pipeline_actions_common.h" #include "hash_func.h" #include "lib_sip_alg.h" #include "vnf_common.h" #include "pipeline_common_be.h" #define SIP_ALG_SIP "SIP" #define SIP_ALG_200_OK "200 OK" #define SIP_ALG_INVITE "INVITE" #define SIP_ALG_BYE "BYE" #define SIP_ALG_TRYING "100 Trying" #define SIP_ALG_RINGING "180 Ringing" #define SIP_ALG_ACK "ACK" #define SIP_ALG_CONTACT "Contact" #define SIP_ALG_CONTENT_LEN "Content-Length" #define SIP_ALG_VIA "Via" #define SIP_ALG_FROM "From" #define SIP_ALG_TO "To" #define SIP_ALG_CALLID "Call-ID" #define SIP_ALG_RTP "RTP" #define SIP_ALG_RTCP "a=RTCP" #define SIP_ALG_CANCEL "CANCEL" #define SIP_ALG_CONTYPE "Content-Type" #define SIP_ALG_APPSDP "application/sdp" #define SIP_ALG_CSEQ "CSeq" #define SIP_ALG_AUDIO "m=audio" #define SIP_ALG_DOUBLE_CRLF "\r\n\r\n" #define SIP_ALG_CRLF "\r\n" #define SIP_ALG_AT "@" #define SIP_ALG_GREAT ">" #define SIP_ALG_OWNER "o=" #define SIP_ALG_IPV4 "IP4" #define SIP_ALG_CONN "c=" #define SIP_ALG_REMOTE_PARTY_ID "Remote-Party-ID" #define SIP_ALG_SPACE " " #define SIP_ALG_SEMICOLON ";" #define SIP_DEFAULT_L4PORT 5060 #define SIP_ALG_INVITE_MSGTYPE 1 #define SIP_ALG_BYE_MSGTYPE 2 #define SIP_ALG_200_OK_INVITE_MSGTYPE 3 #define SIP_ALG_200_OK_BYE_MSGTYPE 4 #define SIP_ALG_TRYING_RINGING_MSGTYPE 5 #define SIP_ALG_ACK_MSGTYPE 6 #define MAX_NUM_SIP_ALG_ENTRIES 16384 #define SIP_ALG_VIA_FIELD_IPADDR 14 #define SIP_ALG_CTAC_FIELD_IPADDR 7 #define ADDRESS_PORT_STRING 1 #define PORT_STRING 2 #define MAX_ADDR_PORT_SIZE 30 #define MAX_ADDR_SIZE 20 #define MAX_PORT_SIZE 10 #define MAX_SIP_UDP_MSG_SIZE 2000 #define ALG_DEBUG 0 enum { FALSE, TRUE }; struct rte_mempool *lib_alg_pktmbuf_tx_pool; struct rte_mbuf *lib_alg_pkt; static struct rte_hash_parameters sip_alg_hash_params = { .name = NULL, .entries = MAX_NUM_SIP_ALG_ENTRIES, .reserved = 0, .key_len = sizeof(struct sip_alg_key), .hash_func = rte_jhash, .hash_func_init_val = 0, .extra_flag = 1, }; struct rte_hash *sip_alg_hash_table; struct sip_alg_table_entry *sip_alg_table[MAX_NUM_SIP_ALG_ENTRIES]; char *sip_alg_process(struct rte_mbuf *pkt, uint16_t pkt_direction, uint16_t call_direction, uint16_t msgType, uint32_t modIp, uint16_t modL4Port, uint32_t pubIp, uint16_t pubL4Port, uint16_t modRtpPort, uint16_t modRtcpPort, uint16_t *diffModSipLen); char *getSipCallIdStr(char *pMsg); char *natSipAlgModifyPayloadAddrPort(char *pSipMsg, char **pSipMsgEnd, uint32_t oldStrLen, uint32_t *diffLen, uint32_t pub_ip, uint16_t pub_port, uint32_t type); char *natSipAlgAdjustMsg(char *pSipMsg, char **pSipMsgEnd, uint32_t newStrLen, uint32_t oldStrLen); // This method will be called from other VNF to initialize SIP lib // Make an API out of it void lib_sip_alg_init(void) { char *s = rte_zmalloc(NULL, 64, RTE_CACHE_LINE_SIZE);; int socketid = 0; /* create ipv4 hash */ if(!s){ printf("NAT SIP ALG Init failed\n"); return; } snprintf(s, strlen(s), "ipv4_sip_alg_hash_%d", socketid); printf("NAT SIP ALG initialization ...\n"); /* SIP ALG hash table initialization */ sip_alg_hash_params.socket_id = SOCKET_ID_ANY; sip_alg_hash_params.name = s; sip_alg_hash_table = rte_hash_create(&sip_alg_hash_params); if (sip_alg_hash_table == NULL) { printf("SIP ALG rte_hash_create failed. socket %d ...\n", sip_alg_hash_params.socket_id); rte_exit(0, "SIP ALG rte_hash_create failed"); } else { printf("sip_alg_hash_table %p\n\n", (void *)sip_alg_hash_table); } } char *itoa(long n); char *itoa(long n) { int len = n == 0 ? 1 : floor(log10l(labs(n))) + 1; if (n < 0) len++; /* room for negative sign '-' */ char *buf = calloc(sizeof(char), len + 1); // +1 for null if(buf != NULL) snprintf(buf, len + 1, "%ld", n); return buf; } struct sip_alg_table_entry *retrieve_sip_alg_entry( struct sip_alg_key *alg_key); struct sip_alg_table_entry *retrieve_sip_alg_entry( struct sip_alg_key *alg_key) { struct sip_alg_table_entry *sip_alg_data = NULL; int ret = rte_hash_lookup(sip_alg_hash_table, alg_key); if (ret < 0) { #ifdef ALGDBG printf("alg-hash lookup failed ret %d, " "EINVAL %d, ENOENT %d\n", ret, EINVAL, ENOENT); #endif } else { sip_alg_data = sip_alg_table[ret]; return sip_alg_data; } return NULL; } //int remove_sip_alg_entry(uint32_t ipaddr, uint16_t portid); int remove_sip_alg_entry(uint32_t ipaddr, uint16_t portid) { struct sip_alg_key alg_key; void *sip_alg_entry_data; int ret; alg_key.l4port = portid; alg_key.ip_address = ipaddr; alg_key.filler1 = 0; alg_key.filler2 = 0; if (ALG_DEBUG) printf("remove_sip_entry ip %x, port %d\n", alg_key.ip_address, alg_key.l4port); ret = rte_hash_lookup(sip_alg_hash_table, &alg_key); if (ret < 0) { if (ALG_DEBUG) printf("removesipalgentry: " "rtehashlookup failed with error %d", ret); return -1; } sip_alg_entry_data = sip_alg_table[ret]; free(sip_alg_entry_data); rte_hash_del_key(sip_alg_hash_table, &alg_key); return 0; } /* * Function for populating SIP ALG entry. return 0 - success & * return -1 - failure */ int populate_sip_alg_entry(uint32_t ipaddr, uint16_t portid, char *sip_call_id, uint8_t call_direction, enum sip_alg_port_type port_type); int populate_sip_alg_entry(uint32_t ipaddr, uint16_t portid, char *sip_call_id, uint8_t call_direction, enum sip_alg_port_type port_type) { struct sip_alg_key alg_key; alg_key.l4port = portid; alg_key.ip_address = ipaddr; alg_key.filler1 = 0; alg_key.filler2 = 0; int ret; if (ALG_DEBUG) printf("populate_sip_alg_entry port %d, ip %x\n", alg_key.l4port, alg_key.ip_address); struct sip_alg_table_entry *new_alg_data = retrieve_sip_alg_entry(&alg_key); if (new_alg_data) { if (ALG_DEBUG) printf("sip_alg_entry exists ip%x, port %d\n", alg_key.ip_address, alg_key.l4port); return 0; } new_alg_data = NULL; new_alg_data = (struct sip_alg_table_entry *) malloc(sizeof(struct sip_alg_table_entry)); if (new_alg_data == NULL) { printf("populate sip alg entry: allocation failed\n"); return -1; } new_alg_data->l4port = portid; new_alg_data->ip_address = ipaddr; new_alg_data->l4port_type = port_type; new_alg_data->sip_alg_call_direction = call_direction; strcpy((char *)new_alg_data->sip_alg_call_id, (char *)sip_call_id); new_alg_data->filler1 = 0; new_alg_data->filler2 = 0; new_alg_data->filler3 = 0; ret = rte_hash_add_key(sip_alg_hash_table, &alg_key); if (ret < 0) { printf("populate sip - rte_hash_add_key_data ERROR %d\n", ret); free(new_alg_data); return -1; } sip_alg_table[ret] = new_alg_data; if (ALG_DEBUG) { printf("SIP_ALG: table update - ip=%x on port=%d ret=%d\n", alg_key.ip_address, portid, ret); } return 0; } int sip_alg_dpi(struct rte_mbuf *pkt, enum pkt_dir pkt_direction, uint32_t modIp, uint16_t modL4Port, uint32_t pubIp, uint16_t pubL4Port, uint16_t modRtpPort, uint16_t modRtcpPort) { uint16_t msgType = 0; enum sip_alg_call_direction call_direction = 0; uint32_t ip_address = 0; uint16_t port = 0; int ret = 0; struct ipv4_hdr *ip_h; struct ether_hdr *eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *); struct udp_hdr *udp_h; char *pSipMsg = NULL; struct sip_alg_table_entry *sip_alg_entry; char *sip_call_id = NULL; int pos = 0; struct sip_alg_key alg_key; uint16_t diffModSipLen = 0; ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr)); udp_h = (struct udp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr)); pSipMsg = ((char *)udp_h + sizeof(struct udp_hdr)); if (ALG_DEBUG) { printf("%s: packet length(%u), buffer length(%u)\n", __func__, rte_pktmbuf_pkt_len(pkt), pkt->buf_len); printf("%s: last segment addr(%p %p)\n", __func__, rte_pktmbuf_lastseg(pkt), pkt); printf("%s: data len(%u, %u)\n", __func__, rte_pktmbuf_data_len(pkt), rte_pktmbuf_data_len(rte_pktmbuf_lastseg(pkt))); printf("%s: buffer addr(%p), data_off(%u), nb_segs(%u)\n", __func__, pkt->buf_addr, pkt->data_off, pkt->nb_segs); } if (IS_STRING_SAME(pSipMsg, SIP_ALG_INVITE)) { /* find the call id position in the message */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) sip_call_id = getSipCallIdStr(pSipMsg + pos + TAG_TO_DATAPOS(SIP_ALG_CALLID)); if (ALG_DEBUG) printf("sipalgdpi: %d call id %s\n", __LINE__, sip_call_id); if (pkt_direction == PRIVATE) { call_direction = SIP_CALL_OUTGOING; ip_address = rte_bswap32(ip_h->src_addr); port = rte_bswap16(udp_h->src_port); } else if (pkt_direction == PUBLIC) { call_direction = SIP_CALL_INCOMING; ip_address = pubIp; port = pubL4Port; } if (ALG_DEBUG) printf("0=>sip_alg_dpi: pkt_dir(%d), call_dir(%d), " "ipaddr(%x) port(%x)\n", pkt_direction, call_direction, ip_address, port); /* add 3 entries in ALG table for SIP, RTP, RTCP */ ret = populate_sip_alg_entry(ip_address, port, sip_call_id, call_direction, SIP_UDP); if (ret < 0) { printf("sipalgdpi:populate SIP alg UDP entry failed\n"); return 0; } if (modRtpPort != 0) { ret = populate_sip_alg_entry(ip_address, modRtpPort, sip_call_id, call_direction, SIP_RTP); if (ret < 0) { printf("sipalgdpi: " "populate SIP alg entry RTP failed\n"); return 0; } } if (modRtcpPort != 0) { ret = populate_sip_alg_entry(ip_address, modRtcpPort, sip_call_id, call_direction, SIP_RTCP); if (ret < 0) { printf("sipalgdpi: " "populate SIP alg entry RTCP failed\n"); return 0; } } /* Call ALG packet process function for checking & payload modification */ pSipMsg = sip_alg_process(pkt, pkt_direction, call_direction, SIP_ALG_INVITE_MSGTYPE, modIp, modL4Port, 0, 0, modRtpPort, modRtcpPort, &diffModSipLen); } else { /* * not SIP INVITE, could be SIP response 200 OK invite, 100 trying, * 180 ringing or BYE or 200 OK BYe */ /* retrieve ALG entry from SIP ALG table */ if (pkt_direction == PRIVATE) { alg_key.ip_address = rte_bswap32(ip_h->src_addr); alg_key.l4port = rte_bswap16(udp_h->src_port); } else { alg_key.ip_address = pubIp; alg_key.l4port = pubL4Port; } alg_key.filler1 = 0; alg_key.filler2 = 0; sip_alg_entry = retrieve_sip_alg_entry(&alg_key); if (ALG_DEBUG) { printf("%s: sip_alg_entry_ptr(%p)\n", __func__, sip_alg_entry); printf("1=>%s: pkt_dir(%d), modIp(%x),modL4Port(%x), " "modRtpPort(%x), modRtcpPort(%x), pubIp(%x), pubL4Port(%x)\n", __func__, pkt_direction, modIp, modL4Port, modRtpPort, modRtcpPort, pubIp, pubL4Port); } if (sip_alg_entry) { call_direction = sip_alg_entry->sip_alg_call_direction; if (IS_STRING_SAME(pSipMsg, SIP_ALG_BYE) || IS_STRING_SAME(pSipMsg, SIP_ALG_CANCEL)) { msgType = SIP_ALG_BYE_MSGTYPE; goto sipAlgProcess; } else if (IS_STRING_SAME(pSipMsg, SIP_ALG_ACK)) { msgType = SIP_ALG_ACK_MSGTYPE; goto sipAlgProcess; } pSipMsg += 8; /* checking if its OK or Trying or Ringing */ if (IS_STRING_SAME(pSipMsg, SIP_ALG_200_OK)) { /* check CSEQ. Based on that update the msg type */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CSEQ, &pos, 0) == TRUE) { char *pBye; pBye = pSipMsg + pos + TAG_TO_DATAPOS(SIP_ALG_CSEQ); SKIP_SPACES(pBye); /* skip the number field */ while (*pBye != ' ') pBye++; SKIP_SPACES(pBye); if (IS_STRING_SAME(pBye, SIP_ALG_BYE) || (IS_STRING_SAME (pBye, SIP_ALG_CANCEL))) msgType = SIP_ALG_200_OK_BYE_MSGTYPE; else msgType = SIP_ALG_200_OK_INVITE_MSGTYPE; } } else if (IS_STRING_SAME(pSipMsg, SIP_ALG_TRYING) || IS_STRING_SAME(pSipMsg, SIP_ALG_RINGING)) { msgType = SIP_ALG_TRYING_RINGING_MSGTYPE; } sipAlgProcess: if (ALG_DEBUG) printf("2=>%s: pkt_dir(%d), call_dir(%d), " "msgType(%d), modIp(%x), modL4Port(%x), " " modRtpPort(%x), modRtcpPort(%x)\n", __func__, pkt_direction, call_direction, msgType, modIp, modL4Port, modRtpPort, modRtcpPort); /* Call SIP alg processing for further processing. */ pSipMsg = sip_alg_process(pkt, pkt_direction, call_direction, msgType, modIp, modL4Port, pubIp, pubL4Port, modRtpPort, modRtcpPort, &diffModSipLen); } else pSipMsg = NULL; } if (ALG_DEBUG) printf("%s: Before IP total length(%u), udp length(%u)\n", __func__, rte_bswap16(ip_h->total_length), rte_bswap16(udp_h->dgram_len)); /* * need to modify mbuf & modified length of payload in the IP/UDP * header length fields and return to CGNAT for transmitting */ uint16_t len = 0; if (diffModSipLen > 0) { len = rte_bswap16(udp_h->dgram_len); len += diffModSipLen; udp_h->dgram_len = rte_bswap16(len); len = rte_bswap16(ip_h->total_length); len += diffModSipLen; ip_h->total_length = rte_bswap16(len); if (rte_pktmbuf_append(pkt, diffModSipLen) == NULL) printf("%s: pktmbuf_append returns NULL", __func__); } if (ALG_DEBUG) printf("%s: After IP total length(%u), udp length(%u), " "diffModSipLen(%u)\n", __func__, rte_bswap16(ip_h->total_length), rte_bswap16(udp_h->dgram_len), diffModSipLen); if (pSipMsg != NULL) return 1; else return 0; } char *sip_alg_process(struct rte_mbuf *pkt, uint16_t pkt_direction, uint16_t call_direction, uint16_t msgType, uint32_t modIp, uint16_t modL4Port, uint32_t pubIp, uint16_t pubL4Port, uint16_t modRtpPort, uint16_t modRtcpPort, uint16_t *diffModSipLen) { struct ipv4_hdr *ip_h; struct ether_hdr *eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *); struct udp_hdr *udp_h; char *pSipMsg, *pStr, *pEndPtr; int pos; /* diff between old & new modified field len */ uint32_t diffLen, addrPortLen; int sdpMsgLen = 0; int sip_msg_len = 0; ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr)); udp_h = (struct udp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr)); pSipMsg = ((char *)udp_h + sizeof(struct udp_hdr)); char *pTmpSipMsg = pSipMsg; char *pStartSipMsg = pSipMsg; sip_msg_len = rte_bswap16(ip_h->total_length) - sizeof(struct ipv4_hdr) - sizeof(struct udp_hdr); if (natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0) == TRUE) pTmpSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN)); else { printf("sip_alg_process: Invalid Content Length\n"); return NULL; } SKIP_SPACES(pTmpSipMsg); int sdpDataLen = strtol(pTmpSipMsg, &pStr, 10); natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_DOUBLE_CRLF, &pos, 0); pTmpSipMsg += (pos + strlen(SIP_ALG_DOUBLE_CRLF)); if (sdpDataLen != 0) if (natSipAlgMsgFieldPos (pTmpSipMsg, SIP_ALG_REMOTE_PARTY_ID, &pos, 0) == TRUE) { pTmpSipMsg += pos + strlen(SIP_ALG_REMOTE_PARTY_ID); /* move further to CRLF which is the end of SIP msg */ natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_DOUBLE_CRLF, &pos, 0); pTmpSipMsg += (pos + strlen(SIP_ALG_DOUBLE_CRLF)); } int sipMsgLen = (pTmpSipMsg - pSipMsg); char *pSipMsgEnd = pSipMsg + sipMsgLen + sdpDataLen; if (ALG_DEBUG) printf("%s: pSipMsg: %p, pSipMsgEnd: %p, sipMsgLen: %d, " "sdpDataLen: %d totalSipMsgLen: %d\n", __func__, pSipMsg, pSipMsgEnd, sipMsgLen, sdpDataLen, sip_msg_len); if (call_direction == SIP_CALL_OUTGOING) { if ((msgType == SIP_ALG_INVITE_MSGTYPE) || (msgType == SIP_ALG_ACK_MSGTYPE)) { /* Get to Via field IP address/Port to modify */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0) == TRUE) { /* advance to IP/Port string */ pSipMsg += (pos + strlen(SIP_ALG_VIA) + SIP_ALG_VIA_FIELD_IPADDR); pTmpSipMsg = pSipMsg; /* move pTmp to next field */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_SEMICOLON, &pos, 0); pTmpSipMsg += pos; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; No valid VIA field\n"); return NULL; } /* Modify VIA field IP addr:port in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ /* Advance to "From" field IP addr in payload */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0) == TRUE) { pSipMsg += pos; /* Moving to "From" */ /* advance to IP/Port string */ pTmpSipMsg = pSipMsg; /* move pTmpSipMsg to str ">" which is end of add:port string */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; diffLen = pTmpSipMsg - pSipMsg; /* find "@" from "From" string to ">" string which is start of "addr:port" */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; /* now its pointing to start of From field "address:port" */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf ("sip_alg_process; No valid From field\n"); return NULL; } /* Modify "From" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ /* Advance to Call id field */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) { pSipMsg += pos; /* moving it to start of string "Call-ID" */ pTmpSipMsg = pSipMsg; /* move tmpSipMsg to next field */ natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; diffLen = pTmpSipMsg - pSipMsg; /* Move pSipMsg to start of Call id "IP addr" string */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; " " No valid Call Id field\n"); return NULL; } /* Modify "Call-id" field "addr:port" in payload */ /* L4 port input is made as 0 as its only addr string modification */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* Advance to "Contact" field */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) { pSipMsg += pos; /* move tmpMsg to CRLF */ pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; /* move sipMsg to addr:port string */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; " "No valid Call Id field\n"); return NULL; } /* Modify "Contact" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; if (msgType == SIP_ALG_INVITE_MSGTYPE) { /* Advance to check content type & get content length (SDP length) */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CONTYPE, &pos, 0) == TRUE) { pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTYPE)); SKIP_SPACES(pSipMsg); /*check the application/sdp type, if not, exit */ if (!IS_STRING_SAME (pSipMsg, SIP_ALG_APPSDP)) { printf("sip_alg_process " "Invalid Content type\n"); return NULL; } } else { printf("sip_alg_process; " "No valid Content field\n"); return NULL; } /* get the SDP content length */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0); pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN)); SKIP_SPACES(pSipMsg); sdpMsgLen = strtol(pSipMsg, &pEndPtr, 10); if (!sdpMsgLen) { /* if ACK message, SDP content wont be there.go to ALG process complete */ if (msgType == SIP_ALG_ACK_MSGTYPE) goto sipAlgProcessExit; printf("sip_alg_process - " "sdpMsgLen is 0\n"); return NULL; } /* Advance to SDP data message Owner address */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_OWNER, &pos, 0) == TRUE) { pSipMsg += pos; /* at start of owner string "o=" */ pTmpSipMsg = pSipMsg; /* move tmmsg to CRLF of owner field */ natSipAlgMsgFieldPosFindCrlf(pSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; /* start of CRLF "/r/n" */ /* move pSipMsg to IP address string in owner field */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_IPV4, &pos, 0); pSipMsg += (pos + strlen(SIP_ALG_IPV4)); SKIP_SPACES(pSipMsg); /* after skipping spaces, pSip at start of addr */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_processing: " "Invalid Owner field\n"); return NULL; } /* Modify "Owner" field "addr" in payload. Input L4 port as 0 */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; sdpMsgLen += diffLen; /* need to adjust the SDP msg len as modification done. */ /* Advance to Connection information to modify IP address */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CONN, &pos, 0) == TRUE) { pSipMsg += pos; pTmpSipMsg = pSipMsg; /* move tmmsg to CRLF of owner field */ natSipAlgMsgFieldPosFindCrlf(pSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; /* start of CRLF "/r/n" */ /* move pSipMsg to IP address string in owner field */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_IPV4, &pos, 0); pSipMsg += (pos + strlen(SIP_ALG_IPV4)); SKIP_SPACES(pSipMsg); /* after skipping spaces, pSip at start of addr */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_processing: " "Invalid Owner field\n"); return NULL; } /* Modify "Connection" field "addr" in payload. Input L4 port as 0 */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; sdpMsgLen += diffLen; /* need to adjust the SDP msg len as modification done. */ /* Advance to RTP audio port */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_AUDIO, &pos, 0) == TRUE) { pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_AUDIO)); SKIP_SPACES(pSipMsg); pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPosFindSpace (pTmpSipMsg, SIP_ALG_SPACE, &pos, 0); pTmpSipMsg += pos; addrPortLen = pTmpSipMsg - pSipMsg; } /* Modify "RTP Audio" port in payload. pass pub_ip as 0. */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, 0, modRtpPort, PORT_STRING); *diffModSipLen += diffLen; sdpMsgLen += diffLen; /* need to adjust the SDP msg len as modification done. */ /* Advance to RTCP control port, if its there */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_RTCP, &pos, 0) == TRUE) { pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_RTCP)); SKIP_SPACES(pSipMsg); pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPosFindSpace (pTmpSipMsg, SIP_ALG_SPACE, &pos, 0); pTmpSipMsg += pos; addrPortLen = pTmpSipMsg - pSipMsg; /* Modify "RTP Audio" port in payload. pass pub_ip as 0. */ pSipMsg = natSipAlgModifyPayloadAddrPort (pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, 0, modRtcpPort, PORT_STRING); *diffModSipLen += diffLen; sdpMsgLen += diffLen; /* need to adjust the SDP msg len as modification done. */ } } /* with this SIP payload modification is complete for outbound invite message */ } else if ((msgType == SIP_ALG_TRYING_RINGING_MSGTYPE) || (msgType == SIP_ALG_200_OK_INVITE_MSGTYPE)) { /* Get to Via field IP address/Port to modify */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0) == TRUE) { /* advance to IP/Port string */ pSipMsg += (pos + strlen(SIP_ALG_VIA) + SIP_ALG_VIA_FIELD_IPADDR); pTmpSipMsg = pSipMsg; /* move pTmp to next field */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_SEMICOLON, &pos, 0); pTmpSipMsg += pos; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; No valid VIA field\n"); return NULL; } /* Modify VIA field IP addr:port in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen = diffLen; /* Advance to "From" field IP addr in payload */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0) == TRUE) { pSipMsg += pos; /* Moving to "From" */ /* advance to IP/Port string */ pTmpSipMsg = pSipMsg; /* move pTmpSipMsg to str ">" which is end of add:port string */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; //diffLen = pTmpSipMsg - pSipMsg; /* find "@" from "From" string to ">" string which is start of "addr:port" */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; /* now its pointing to start of From field "address:port" */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf ("sip_alg_process; No valid From field\n"); return NULL; } /* Modify "From" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ /* Advance to Call id field */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) { pSipMsg += pos; /* moving it to start of string "Call-ID" */ pTmpSipMsg = pSipMsg; /* move tmpSipMsg to next field */ natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; //diffLen = pTmpSipMsg - pSipMsg; /* Move pSipMsg to start of Call id "IP addr" string */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; " "No valid Call Id field\n"); return NULL; } /* Modify "Call-id" field "addr" in payload */ /* L4 port input is made as 0 as its only addr string modification */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; } else if (pkt_direction == PRIVATE && msgType == SIP_ALG_BYE_MSGTYPE) { /* change via, from, call-id and contact field */ /* Get to Via field IP address to modify */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0) == TRUE) { /* advance to IP/Port string */ pSipMsg += (pos + strlen(SIP_ALG_VIA) + SIP_ALG_VIA_FIELD_IPADDR); pTmpSipMsg = pSipMsg; /* move pTmp to next field */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_SEMICOLON, &pos, 0); pTmpSipMsg += pos; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; No valid VIA field\n"); return NULL; } /* Modify VIA field IP addr in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen = diffLen; /* Advance to "From" field IP addr in payload */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0) == TRUE) { pSipMsg += pos; /* Moving to "From" */ /* advance to IP/Port string */ pTmpSipMsg = pSipMsg; /* move pTmpSipMsg to str ">" which is end of add:port string */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; diffLen = pTmpSipMsg - pSipMsg; /* find "@" from "From" string to ">" string which is start of "addr:port" */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; /* now its pointing to start of From field "address:port" */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf ("sip_alg_process; No valid From field\n"); return NULL; } /* Modify "From" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ /* Advance to Call id field */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) { pSipMsg += pos; /* moving it to start of string "Call-ID" */ pTmpSipMsg = pSipMsg; /* move tmpSipMsg to next field */ natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; diffLen = pTmpSipMsg - pSipMsg; /* Move pSipMsg to start of Call id "IP addr" string */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; " "No valid Call Id field\n"); return NULL; } /* Modify "Call-id" field "addr:port" in payload */ /* L4 port input is made as 0 as its only addr string modification */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* Advance to "Contact" field */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) { pSipMsg += pos; /* move tmpMsg to semicolon */ pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; /* move sipMsg to addr:port string */ int flag = 0; if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0) == FALSE) flag = 1; if (flag) goto SipMsgAdvance2; pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; " "No valid Call Id field\n"); return NULL; } /* Modify "Contact" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; } else if (pkt_direction == PUBLIC && msgType == SIP_ALG_BYE_MSGTYPE) { /* * Modify Bye URL (if its BYE), To field, * Call-Id if call triggered from private, then modify */ /* need to modify address:Port in Bye message string. */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPosFindSpace(pTmpSipMsg, SIP_ALG_SPACE, &pos, 0); pTmpSipMsg += pos; addrPortLen = pTmpSipMsg - pSipMsg; /* modify the "addr:port" in Bye message line */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ /* Advance to 'To" field */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0) == TRUE) { pSipMsg += pos; pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ } /* check for Call-Id. */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) { pSipMsg += pos; /* moving it to start of string "Call-ID" */ pTmpSipMsg = pSipMsg; /* move tmpSipMsg to next field */ natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; //diffLen = pTmpSipMsg - pSipMsg; /* Move pSipMsg to start of Call id "IP addr" string */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; " "No valid Call Id field\n"); return NULL; } /* Modify "Call-id" field "addr" in payload */ /* L4 port input is made as 0 as its only addr string modification */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; } else if (pkt_direction == PRIVATE && (msgType == SIP_ALG_200_OK_BYE_MSGTYPE)) { /* * Need to modify To field, Call-Id, * Contact if call triggered from private, then modify */ /* Get to To field IP address to modify */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0) == TRUE) { pSipMsg += pos; /* Moving to "From" */ /* advance to IP/Port string */ pTmpSipMsg = pSipMsg; /* move pTmpSipMsg to str ">" which is end of add:port string */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; diffLen = pTmpSipMsg - pSipMsg; /* find "@" from "From" string to ">" string which is start of "addr:port" */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; /* now its pointing to start of From field "address:port" */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf ("sip_alg_process; no valid from field\n"); return NULL; } /* Modify "From" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen = diffLen; /* increase the overall diff between old & mod sip msg */ /* Advance to "Contact" field */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) { pSipMsg += pos; /* move tmpMsg to CRLF */ pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; /* move sipMsg to addr:port string */ int flag = 0; if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0) == FALSE) flag = 1; if (flag) goto SipMsgAdvance2; pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; " "No valid Call Id field\n"); return NULL; } /* Modify "Contact" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; } else if (pkt_direction == PUBLIC && (msgType == SIP_ALG_200_OK_BYE_MSGTYPE)) { /* change via and from field, call-id field */ /* Get to Via field IP address to modify */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0) == TRUE) { /* advance to IP/Port string */ pSipMsg += (pos + strlen(SIP_ALG_VIA) + SIP_ALG_VIA_FIELD_IPADDR); pTmpSipMsg = pSipMsg; /* move pTmp to next field */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_SEMICOLON, &pos, 0); pTmpSipMsg += pos; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; No valid VIA field\n"); return NULL; } /* Modify VIA field IP addr in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen = diffLen; /* Advance to "From" field IP addr in payload */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0) == TRUE) { pSipMsg += pos; /* Moving to "From" */ /* advance to IP/Port string */ pTmpSipMsg = pSipMsg; /* move pTmpSipMsg to str ">" which is end of add:port string */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; diffLen = pTmpSipMsg - pSipMsg; /* find "@" from "From" string to ">" string which is start of "addr:port" */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; /* now its pointing to start of From field "address:port" */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf ("sip_alg_process; No valid From field\n"); return NULL; } /* Modify "From" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* check for Call-Id. */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) { pSipMsg += pos; /* Call id 'addr" need to modified. */ pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; /* modify call id "addr" */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ } else { printf("sip_alg_process; " "no valid Call-id field\n"); return NULL; } /* increase the overall diff between old & mod sip msg */ } } else if (call_direction == SIP_CALL_INCOMING) { if ((msgType == SIP_ALG_INVITE_MSGTYPE) || (msgType == SIP_ALG_ACK_MSGTYPE)) { /* need to modify Invite RL, TO field */ /* move to Invite RL IP address string */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0) == TRUE) { pSipMsg += pos + 1; pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_SIP, &pos, 0); pTmpSipMsg += (pos - 1); /* pointing to space before SIP/2.0 */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf ("sip_alg_process: %d Invalid Invite RL\n", __LINE__); return NULL; } /* modify Invite RL URI in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ /* Advance to 'To" field */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0) == TRUE) { pSipMsg += pos; pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_processing; " "%d Invalid To field\n", __LINE__); return NULL; } /* Modify TO field IP addr:port in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ } else if ((msgType == SIP_ALG_TRYING_RINGING_MSGTYPE) || (msgType == SIP_ALG_200_OK_INVITE_MSGTYPE)) { /* Need to modify TO field */ /* Advance to 'To" field */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0) == TRUE) { pSipMsg += pos; pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ } if (msgType == SIP_ALG_200_OK_INVITE_MSGTYPE) { /* need to modify Contact, Remote-Party Id, SDP O=IN, C=IN, Audio Port */ /* Advance to "Contact" field */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) { pSipMsg += pos; /* move tmpMsg to CRLF */ pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_SEMICOLON, &pos, 0); pTmpSipMsg += pos; /* move sipMsg to addr:port string */ int flag = 0; if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 30) == FALSE) flag = 1; if (flag) goto SipMsgAdvance; pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; " "No valid Call Id field\n"); return NULL; } /* Modify "Contact" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; SipMsgAdvance: /* advance to Remote-Party Id */ pTmpSipMsg = pSipMsg; if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_REMOTE_PARTY_ID, &pos, 0) == TRUE) { pSipMsg += pos + strlen(SIP_ALG_REMOTE_PARTY_ID); pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; /* modify the field */ pSipMsg = natSipAlgModifyPayloadAddrPort (pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); diffModSipLen += diffLen; } else { printf("sip_alg_process: " "Remote-party-id is not in the msg\n"); pSipMsg = pTmpSipMsg; } /* Advance to SDP data message Owner address */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_OWNER, &pos, 0) == TRUE) { pSipMsg += pos; /* at start of owner string "o=" */ pTmpSipMsg = pSipMsg; /* move tmmsg to CRLF of owner field */ natSipAlgMsgFieldPosFindCrlf(pSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; /* start of CRLF "/r/n" */ /* move pSipMsg to IP address string in owner field */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_IPV4, &pos, 0); pSipMsg += (pos + strlen(SIP_ALG_IPV4)); SKIP_SPACES(pSipMsg); /* after skipping spaces, pSip at start of addr */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_processing: " "Invalid Owner field\n"); return NULL; } /* Modify "Owner" field "addr" in payload. Input L4 port as 0 */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; sdpMsgLen += diffLen; /* update the sdpMsgLen after modification */ /* Advance to Connection information to modify IP address */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CONN, &pos, 0) == TRUE) { pSipMsg += pos; pTmpSipMsg = pSipMsg; /* move tmmsg to CRLF of owner field */ natSipAlgMsgFieldPosFindCrlf(pSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; /* start of CRLF "/r/n" */ /* move pSipMsg to IP address string in owner field */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_IPV4, &pos, 0); pSipMsg += (pos + strlen(SIP_ALG_IPV4)); SKIP_SPACES(pSipMsg); /* after skipping spaces, pSip at start of addr */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_processing: " "Invalid Connection field\n"); return NULL; } /* Modify "Connection" field "addr" in payload. Input L4 port as 0 */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; sdpMsgLen += diffLen; /* update the sdpMsgLen after modification */ /* Advance to RTP audio port */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_AUDIO, &pos, 0) == TRUE) { pSipMsg += (pos + strlen(SIP_ALG_AUDIO)); SKIP_SPACES(pSipMsg); pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPosFindSpace (pTmpSipMsg, SIP_ALG_SPACE, &pos, 0); pTmpSipMsg += pos; addrPortLen = pTmpSipMsg - pSipMsg; } /* Modify "RTP Audio" port in payload. pass pub_ip as 0. */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, 0, modRtpPort, PORT_STRING); *diffModSipLen += diffLen; sdpMsgLen += diffLen; /* update the sdpMsgLen after modification */ } } else if (pkt_direction == PUBLIC && msgType == SIP_ALG_BYE_MSGTYPE) { /* Modify Bye URL (if its BYE), To field */ /* need to modify address:Port in Bye message string. */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPosFindSpace(pTmpSipMsg, SIP_ALG_SPACE, &pos, 0); pTmpSipMsg += pos; addrPortLen = pTmpSipMsg - pSipMsg; /* modify the "addr:port" in Bye message line */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ /* Advance to 'To" field */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0) == TRUE) { pSipMsg += pos; pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ } else { printf ("sip_alg_processing: Invalid TO field\n"); return NULL; } } else if (pkt_direction == PRIVATE && msgType == SIP_ALG_BYE_MSGTYPE) { /* change via and from field */ /* Get to Via field IP address to modify */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0) == TRUE) { /* advance to IP/Port string */ pSipMsg += (pos + strlen(SIP_ALG_VIA) + SIP_ALG_VIA_FIELD_IPADDR); pTmpSipMsg = pSipMsg; /* move pTmp to next field */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_SEMICOLON, &pos, 0); pTmpSipMsg += pos; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; No valid VIA field\n"); return NULL; } /* Modify VIA field IP addr in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen = diffLen; /* Advance to "From" field IP addr in payload */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0) == TRUE) { pSipMsg += pos; /* Moving to "From" */ /* advance to IP/Port string */ pTmpSipMsg = pSipMsg; /* move pTmpSipMsg to str ">" which is end of add:port string */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; diffLen = pTmpSipMsg - pSipMsg; /* find "@" from "From" string to ">" string which is start of "addr:port" */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; /* now its pointing to start of From field "address:port" */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf ("sip_alg_process; No valid From field\n"); return NULL; } /* Modify "From" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ } else if (pkt_direction == PRIVATE && msgType == SIP_ALG_200_OK_BYE_MSGTYPE) { /* change via and from field */ /* Get to Via field IP address to modify */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0) == TRUE) { /* advance to IP/Port string */ pSipMsg += (pos + strlen(SIP_ALG_VIA) + SIP_ALG_VIA_FIELD_IPADDR); pTmpSipMsg = pSipMsg; /* move pTmp to next field */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_SEMICOLON, &pos, 0); pTmpSipMsg += pos; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; No valid VIA field\n"); return NULL; } /* Modify VIA field IP addr in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, 0, ADDRESS_PORT_STRING); *diffModSipLen = diffLen; /* Advance to "From" field IP addr in payload */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0) == TRUE) { pSipMsg += pos; /* Moving to "From" */ /* advance to IP/Port string */ pTmpSipMsg = pSipMsg; /* move pTmpSipMsg to str ">" which is end of add:port string */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; diffLen = pTmpSipMsg - pSipMsg; /* find "@" from "From" string to ">" string which is start of "addr:port" */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; /* now its pointing to start of From field "address:port" */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf ("sip_alg_process; No valid From field\n"); return NULL; } /* Modify "From" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; /* increase the overall diff between old & mod sip msg */ } else if (pkt_direction == PUBLIC && msgType == SIP_ALG_200_OK_BYE_MSGTYPE) { /* Get to To field IP address to modify */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0) == TRUE) { pSipMsg += pos; /* Moving to "From" */ /* advance to IP/Port string */ pTmpSipMsg = pSipMsg; /* move pTmpSipMsg to str ">" which is end of add:port string */ natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT, &pos, 0); pTmpSipMsg += pos; diffLen = pTmpSipMsg - pSipMsg; /* find "@" from "From" string to ">" string which is start of "addr:port" */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; /* now its pointing to start of From field "address:port" */ addrPortLen = pTmpSipMsg - pSipMsg; } else { printf ("sip_alg_process; no valid from field\n"); return NULL; } /* Modify "From" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen = diffLen; /* increase the overall diff between old & mod sip msg */ /* Advance to "Contact" field */ if (natSipAlgMsgFieldPos (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) { pSipMsg += pos; /* move tmpMsg to CRLF */ pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_CRLF, &pos, 0); pTmpSipMsg += pos; /* move sipMsg to addr:port string */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0); pSipMsg += pos + 1; addrPortLen = pTmpSipMsg - pSipMsg; } else { printf("sip_alg_process; " "No valid Call Id field\n"); return NULL; } /* Modify "Contact" field "addr:port" in payload */ pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd, addrPortLen, &diffLen, modIp, modL4Port, ADDRESS_PORT_STRING); *diffModSipLen += diffLen; } } SipMsgAdvance2: /* need to remove the SIP ALG entry if msg is 200 OK BYE response */ if (call_direction == SIP_CALL_OUTGOING) { /* call remove sip alg entry here */ if (pkt_direction == PRIVATE) { if (msgType == SIP_ALG_200_OK_BYE_MSGTYPE) { if (remove_sip_alg_entry (rte_bswap32(ip_h->src_addr), rte_bswap16(udp_h->src_port)) < 0) printf("removesipalgentry failed: " "ipaddr %d, portid %d\n", ip_h->src_addr, udp_h->src_port); } } } else { if (pkt_direction == PUBLIC) { if (msgType == SIP_ALG_200_OK_BYE_MSGTYPE) { if (remove_sip_alg_entry(pubIp, pubL4Port) < 0) printf("removesipalgentry failed: " " ipaddr %d, portid %d\n", pubIp, pubL4Port); } } } /* adjust SDP msg len (sdpMsgLen) in the content length field of SIP msg */ if ((sdpMsgLen > 0) && (sdpDataLen > 0)) { pSipMsg = pStartSipMsg; char *tmpSdpLen = NULL; sdpMsgLen += sdpDataLen; tmpSdpLen = itoa(sdpMsgLen); int tmpStrLen = strlen(tmpSdpLen); /* move to Content length field & change the length to sipMsgLen */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0) == TRUE) { pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN)); SKIP_SPACES(pSipMsg); pTmpSipMsg = pSipMsg; natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_DOUBLE_CRLF, &pos, 0); pTmpSipMsg += pos; SKIP_SPACES(pSipMsg); diffLen = pTmpSipMsg - pSipMsg; natSipAlgAdjustMsg(pSipMsg, &pSipMsgEnd, tmpStrLen, diffLen); strncpy(pSipMsg, tmpSdpLen, tmpStrLen); } else { printf("sip_alg_process: Invalid Content Length\n"); return NULL; } } sipAlgProcessExit: /* need to return toe start of the SIP msg */ return pStartSipMsg; } /* * Function to Fetch RTP & RTCP port & return. Invoked by CGNAT * while adding NAPT entry for RTP & RTCP */ int natSipAlgGetAudioPorts(struct rte_mbuf *pkt, uint16_t *rtpPort, uint16_t *rtcpPort) { struct ipv4_hdr *ip_h; struct ether_hdr *eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *); struct udp_hdr *udp_h; char *pSipMsg, *pEndPtr; int pos, sdpMsgLen; ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr)); udp_h = (struct udp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr)); pSipMsg = ((char *)udp_h + sizeof(struct udp_hdr)); /* Advance to check content type & get content length (SDP length) */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTYPE, &pos, 0) == FALSE) return -1; pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTYPE)); SKIP_SPACES(pSipMsg); /*check the application/sdp type, if not, exit */ if (!IS_STRING_SAME(pSipMsg, SIP_ALG_APPSDP)) { printf("sip_alg_getAudioPort Invalid Content type\n"); return -1; } /* get the SDP content length */ natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0); pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN)); SKIP_SPACES(pSipMsg); sdpMsgLen = strtol(pSipMsg, &pEndPtr, 10); if (!sdpMsgLen) { printf("sipAlggetAudioport - sdpMsgLen is 0\n"); return -1; } /* advance to RTP audio port */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AUDIO, &pos, 0) == TRUE) { pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_AUDIO)); SKIP_SPACES(pSipMsg); *rtpPort = strtol(pSipMsg, &pEndPtr, 10); } else *rtpPort = 0; /* advance to RTCP audio control port */ if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_RTCP, &pos, 0) == TRUE) { pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_RTCP)); SKIP_SPACES(pSipMsg); *rtcpPort = strtol(pSipMsg, &pEndPtr, 10); } else *rtcpPort = 0; if (ALG_DEBUG) printf(" sipAlgGetAudioPort; rtpPort %d, rtcpPort %d\n", *rtpPort, *rtcpPort); return 0; } /* function to find SPACES in ALG message */ int natSipAlgMsgFieldPosFindSpace(char *pData, const char *pIdStr, int *pPos, int searchLen) { char *pStart = pData; int i = 0; if (!pIdStr) return FALSE; if (!searchLen) searchLen = 1500; /* max default search length */ while (TRUE) { while (*pData != ' ') { pData++; i++; } if (i > searchLen) { printf("SIP ALG Find Field Pos: " "Single message exceeds max len: %d\n", searchLen); *pPos = searchLen; /* reaches the end */ return FALSE; } if (bcmp(pData, pIdStr, strlen(pIdStr)) == 0) break; } *pPos = pData - pStart; return TRUE; } /* function to find CRLF in ALG message */ int natSipAlgMsgFieldPosFindCrlf( char *pData, const char *pIdStr, int *pPos, int searchLen) { char *pStart = pData; int i = 0; if (!pIdStr) return FALSE; if (!searchLen) searchLen = 1500; /* max default search length */ while (TRUE) { while (*pData != '\r' && *(pData + 1) != '\n') { pData++; i++; } if (i >= searchLen) { printf("SIP ALG Find Field Pos: " " Single message exceeds max len: %d\n", searchLen); *pPos = searchLen; /* reaches the end */ return FALSE; } if (bcmp(pData, pIdStr, strlen(pIdStr)) == 0) break; } *pPos = pData - pStart; return TRUE; } /* function to find field position in ALG message */ int natSipAlgMsgFieldPos(char *pData, const char *pIdStr, int *pPos, int searchLen) { char *pStart = pData; int i = 0, j = 0; if (!pIdStr) return FALSE; if (!searchLen) searchLen = 1500; /* max default search length */ while (TRUE) { while (*pData != '\r' && *(pData + 1) != '\n') { /* skip all space */ while (*pData == ' ') { pData++; j++; } if (*pData == '\r' && *(pData + 1) == '\n') break; if (bcmp(pData, pIdStr, strlen(pIdStr)) == 0) { *pPos = pData - pStart; return TRUE; } pData++; j++; if (j >= searchLen) { *pPos = pData - pStart; return FALSE; } } /* advance to next line */ for (i = 0; i < (searchLen - 1); i++) { if (pData[i] == '\r') if (pData[i + 1] == '\n') break; } if (i > searchLen) { printf("SIP ALG Find Field Pos: " "Single message exceeds max len: %d\n", searchLen); *pPos = searchLen; /* reaches the end */ return FALSE; } pData += i + 2; searchLen -= (i + 2); if ((pData[0] == '\r' && pData[1] == '\n') || (searchLen <= 0)) { /* reach the end mark \r\n\r\n */ if (searchLen > 0) { pData += 2; continue; } *pPos = pData - pStart; return FALSE; } } *pPos = pData - pStart; return TRUE; } /* get SIP Call id string */ char *getSipCallIdStr(char *pMsg) { char *pStart; char *pCallId = NULL; int i; pStart = pMsg; for (i = 0; i < 200; i++) { if (*pMsg != '\r') pMsg++; else break; } if (i >= 200) { printf("SIP_ALG: getCallid wrong string format\n"); return NULL; } size_t size = RTE_CACHE_LINE_ROUNDUP(pMsg - pStart + 1); pCallId = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); if (!pCallId) return NULL; bcopy(pStart, pCallId, pMsg - pStart); *(pCallId + (pMsg - pStart)) = 0; if (ALG_DEBUG) printf("%s: %s\n", __func__, pCallId); return pCallId; } char *natSipAlgModifyPayloadAddrPort( char *pSipMsg, char **pSipMsgEnd, uint32_t oldStrLen, uint32_t *diffLen, uint32_t modIp, uint16_t modPort, uint32_t type) { char addrport[MAX_ADDR_PORT_SIZE]; struct in_addr ipAddr; uint32_t newStrLen = 0; char *tmpPort = NULL; if (modPort != 0) tmpPort = itoa(modPort); *diffLen = 0; if (type == ADDRESS_PORT_STRING) { ipAddr.s_addr = htonl(modIp); char *tmpAddr = inet_ntoa(ipAddr); if (modPort != 0) /* for addr:port combo modification */ sprintf(addrport, "%s:%s", tmpAddr, tmpPort); else /* if only address modification */ sprintf(addrport, "%s", tmpAddr); newStrLen = strlen(addrport); if (abs(newStrLen - oldStrLen) > 0) { /* * Call the function moving the SIP Msg pointer * to modify the field */ natSipAlgAdjustMsg(pSipMsg, pSipMsgEnd, newStrLen, oldStrLen); } /* replace the old addr:port with new addr:port */ strncpy(pSipMsg, addrport, strlen(addrport)); } else if (type == PORT_STRING) { /* only port modification */ if(tmpPort) newStrLen = strlen(tmpPort); if (abs(newStrLen - oldStrLen) > 0) { /* * Call the function moving the SIP msg pointer * to modify the field */ natSipAlgAdjustMsg(pSipMsg, pSipMsgEnd, newStrLen, oldStrLen); } /* replace the old port with new port */ if(tmpPort) strncpy(pSipMsg, tmpPort, strlen(tmpPort)); } /* output difflen between old str len & modified new str length */ if (newStrLen > oldStrLen) *diffLen = newStrLen - oldStrLen; return pSipMsg; /* modified SIP Msg */ } char *natSipAlgAdjustMsg(char *pSipMsg, char **pSipMsgEnd, uint32_t newStrLen, uint32_t oldStrLen) { char MsgBuffer[MAX_SIP_UDP_MSG_SIZE]; if (newStrLen > oldStrLen) { pSipMsg += oldStrLen; int msgLen = *pSipMsgEnd - pSipMsg; strncpy(MsgBuffer, pSipMsg, msgLen); pSipMsg += (newStrLen - oldStrLen); strncpy(pSipMsg, MsgBuffer, msgLen); if (ALG_DEBUG) printf("natSipAlgAdjustMsg: %u\n", msgLen); /* moving output end of SIP MSG by difflen like pSipMsg */ *pSipMsgEnd += (newStrLen - oldStrLen); } else { /* Setting space on the oldStr position */ memset(pSipMsg, ' ', oldStrLen); } return pSipMsg; } /* end of file */