summaryrefslogtreecommitdiffstats
path: root/common/VIL/alg/lib_sip_alg.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/VIL/alg/lib_sip_alg.c')
-rw-r--r--common/VIL/alg/lib_sip_alg.c2257
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 */