diff options
Diffstat (limited to 'common/VIL/alg/lib_sip_alg.c')
-rw-r--r-- | common/VIL/alg/lib_sip_alg.c | 2257 |
1 files changed, 2257 insertions, 0 deletions
diff --git a/common/VIL/alg/lib_sip_alg.c b/common/VIL/alg/lib_sip_alg.c new file mode 100644 index 00000000..9940d59a --- /dev/null +++ b/common/VIL/alg/lib_sip_alg.c @@ -0,0 +1,2257 @@ +/* +// 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 <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <arpa/inet.h> +#include <math.h> + +#include <app.h> +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_ip.h> +#include <rte_udp.h> +#include <rte_byteorder.h> +#include <rte_table_lpm.h> +#include <rte_table_hash.h> +#include <rte_pipeline.h> +#include <rte_arp.h> +#include <rte_icmp.h> +#include <rte_hash.h> +#include <rte_jhash.h> +#include <rte_cycles.h> + +#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 */ |