Fix support for old DPDK (such as 16.04)
[samplevnf.git] / common / VIL / alg / lib_sip_alg.c
1 /*
2 // Copyright (c) 2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 /*Sriramajeyam*/
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <stdint.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <arpa/inet.h>
23 #include <math.h>
24
25 #include <app.h>
26 #include <rte_common.h>
27 #include <rte_malloc.h>
28 #include <rte_ip.h>
29 #include <rte_udp.h>
30 #include <rte_byteorder.h>
31 #include <rte_table_lpm.h>
32 #include <rte_table_hash.h>
33 #include <rte_pipeline.h>
34 #include <rte_arp.h>
35 #include <rte_icmp.h>
36 #include <rte_hash.h>
37 #include <rte_jhash.h>
38 #include <rte_cycles.h>
39
40 #include "pipeline_actions_common.h"
41 #include "hash_func.h"
42 #include "lib_sip_alg.h"
43 #include "vnf_common.h"
44 #include "pipeline_common_be.h"
45
46 #define SIP_ALG_SIP "SIP"
47 #define SIP_ALG_200_OK "200 OK"
48 #define SIP_ALG_INVITE "INVITE"
49 #define SIP_ALG_BYE "BYE"
50 #define SIP_ALG_TRYING "100 Trying"
51 #define SIP_ALG_RINGING "180 Ringing"
52 #define SIP_ALG_ACK "ACK"
53 #define SIP_ALG_CONTACT "Contact"
54 #define SIP_ALG_CONTENT_LEN "Content-Length"
55 #define SIP_ALG_VIA "Via"
56 #define SIP_ALG_FROM "From"
57 #define SIP_ALG_TO "To"
58 #define SIP_ALG_CALLID "Call-ID"
59 #define SIP_ALG_RTP "RTP"
60 #define SIP_ALG_RTCP "a=RTCP"
61 #define SIP_ALG_CANCEL "CANCEL"
62 #define SIP_ALG_CONTYPE "Content-Type"
63 #define SIP_ALG_APPSDP "application/sdp"
64 #define SIP_ALG_CSEQ "CSeq"
65 #define SIP_ALG_AUDIO "m=audio"
66 #define SIP_ALG_DOUBLE_CRLF "\r\n\r\n"
67 #define SIP_ALG_CRLF "\r\n"
68 #define SIP_ALG_AT "@"
69 #define SIP_ALG_GREAT ">"
70 #define SIP_ALG_OWNER "o="
71 #define SIP_ALG_IPV4 "IP4"
72 #define SIP_ALG_CONN "c="
73 #define SIP_ALG_REMOTE_PARTY_ID "Remote-Party-ID"
74 #define SIP_ALG_SPACE " "
75 #define SIP_ALG_SEMICOLON ";"
76
77 #define SIP_DEFAULT_L4PORT 5060
78
79 #define SIP_ALG_INVITE_MSGTYPE 1
80 #define SIP_ALG_BYE_MSGTYPE 2
81 #define SIP_ALG_200_OK_INVITE_MSGTYPE 3
82 #define SIP_ALG_200_OK_BYE_MSGTYPE 4
83 #define SIP_ALG_TRYING_RINGING_MSGTYPE 5
84 #define SIP_ALG_ACK_MSGTYPE 6
85
86 #define MAX_NUM_SIP_ALG_ENTRIES 16384
87
88 #define SIP_ALG_VIA_FIELD_IPADDR   14
89 #define SIP_ALG_CTAC_FIELD_IPADDR  7
90
91 #define ADDRESS_PORT_STRING   1
92 #define PORT_STRING           2
93
94 #define MAX_ADDR_PORT_SIZE 30
95 #define MAX_ADDR_SIZE 20
96 #define MAX_PORT_SIZE 10
97 #define MAX_SIP_UDP_MSG_SIZE 2000
98
99 #define ALG_DEBUG 0
100
101 enum { FALSE, TRUE };
102
103 struct rte_mempool *lib_alg_pktmbuf_tx_pool;
104
105 struct rte_mbuf *lib_alg_pkt;
106
107 static struct rte_hash_parameters sip_alg_hash_params = {
108         .name = NULL,
109         .entries = MAX_NUM_SIP_ALG_ENTRIES,
110         .reserved = 0,
111         .key_len = sizeof(struct sip_alg_key),
112         .hash_func = rte_jhash,
113         .hash_func_init_val = 0,
114         .extra_flag = 1,
115 };
116
117 struct rte_hash *sip_alg_hash_table;
118
119 struct sip_alg_table_entry *sip_alg_table[MAX_NUM_SIP_ALG_ENTRIES];
120
121 char *sip_alg_process(struct rte_mbuf *pkt,
122                                         uint16_t pkt_direction, uint16_t call_direction,
123                                         uint16_t msgType, uint32_t modIp,
124                                         uint16_t modL4Port, uint32_t pubIp,
125                                         uint16_t pubL4Port, uint16_t modRtpPort,
126                                         uint16_t modRtcpPort, uint16_t *diffModSipLen);
127 char *getSipCallIdStr(char *pMsg);
128 char *natSipAlgModifyPayloadAddrPort(char *pSipMsg, char **pSipMsgEnd,
129                                                  uint32_t oldStrLen, uint32_t *diffLen,
130                                                  uint32_t pub_ip, uint16_t pub_port,
131                                                  uint32_t type);
132 char *natSipAlgAdjustMsg(char *pSipMsg, char **pSipMsgEnd,
133                          uint32_t newStrLen, uint32_t oldStrLen);
134
135 // This method will be called from other VNF to initialize SIP lib
136 // Make an API out of it
137 void lib_sip_alg_init(void)
138 {
139         char *s = rte_zmalloc(NULL, 64, RTE_CACHE_LINE_SIZE);;
140         int socketid = 0;
141         /* create ipv4 hash */
142         if(!s){
143                 printf("NAT SIP ALG Init failed\n");
144                 return;
145         }
146         snprintf(s, strlen(s), "ipv4_sip_alg_hash_%d", socketid);
147         printf("NAT SIP ALG initialization ...\n");
148
149         /* SIP ALG hash table initialization */
150         sip_alg_hash_params.socket_id = SOCKET_ID_ANY;
151         sip_alg_hash_params.name = s;
152         sip_alg_hash_table = rte_hash_create(&sip_alg_hash_params);
153
154         if (sip_alg_hash_table == NULL) {
155                 printf("SIP ALG rte_hash_create failed. socket %d ...\n",
156                                          sip_alg_hash_params.socket_id);
157                 rte_exit(0, "SIP ALG rte_hash_create failed");
158         } else {
159                 printf("sip_alg_hash_table %p\n\n", (void *)sip_alg_hash_table);
160         }
161
162 }
163
164 char *itoa(long n);
165 char itoa_buf[25];
166 char *itoa(long n)
167 {
168         int len = n == 0 ? 1 : floor(log10l(labs(n))) + 1;
169
170         if (n < 0)
171                 len++;          /* room for negative sign '-' */
172
173         snprintf(itoa_buf, len + 1, "%ld", n);
174         return (char *)&itoa_buf;
175 }
176
177 struct sip_alg_table_entry *retrieve_sip_alg_entry(
178                         struct sip_alg_key *alg_key);
179
180 struct sip_alg_table_entry *retrieve_sip_alg_entry(
181                         struct sip_alg_key *alg_key)
182 {
183         struct sip_alg_table_entry *sip_alg_data = NULL;
184
185         int ret = rte_hash_lookup(sip_alg_hash_table, alg_key);
186
187         if (ret < 0) {
188                 #ifdef ALGDBG
189                         printf("alg-hash lookup failed ret %d, "
190                                         "EINVAL %d, ENOENT %d\n",
191                                          ret, EINVAL, ENOENT);
192                 #endif
193         } else {
194                 sip_alg_data = sip_alg_table[ret];
195                 return sip_alg_data;
196         }
197
198         return NULL;
199 }
200
201 //int remove_sip_alg_entry(uint32_t ipaddr, uint16_t portid);
202 int remove_sip_alg_entry(uint32_t ipaddr, uint16_t portid)
203 {
204         struct sip_alg_key alg_key;
205         void *sip_alg_entry_data;
206         int ret;
207
208         alg_key.l4port = portid;
209         alg_key.ip_address = ipaddr;
210         alg_key.filler1 = 0;
211         alg_key.filler2 = 0;
212
213         if (ALG_DEBUG)
214                 printf("remove_sip_entry ip %x, port %d\n", alg_key.ip_address,
215                                          alg_key.l4port);
216
217         ret = rte_hash_lookup(sip_alg_hash_table, &alg_key);
218         if (ret < 0) {
219                 if (ALG_DEBUG)
220                         printf("removesipalgentry: "
221                                 "rtehashlookup failed with error %d",
222                                          ret);
223                 return -1;
224         }
225
226         sip_alg_entry_data = sip_alg_table[ret];
227
228         free(sip_alg_entry_data);
229         rte_hash_del_key(sip_alg_hash_table, &alg_key);
230
231         return 0;
232 }
233
234 /*
235  * Function for populating SIP ALG entry. return 0 - success &
236  * return -1 - failure
237  */
238 int populate_sip_alg_entry(uint32_t ipaddr, uint16_t portid,
239                                  char *sip_call_id, uint8_t call_direction,
240                                  enum sip_alg_port_type port_type);
241 int populate_sip_alg_entry(uint32_t ipaddr, uint16_t portid,
242                                  char *sip_call_id, uint8_t call_direction,
243                                  enum sip_alg_port_type port_type)
244 {
245         struct sip_alg_key alg_key;
246
247         alg_key.l4port = portid;
248         alg_key.ip_address = ipaddr;
249         alg_key.filler1 = 0;
250         alg_key.filler2 = 0;
251         int ret;
252
253         if (ALG_DEBUG)
254                 printf("populate_sip_alg_entry port %d, ip %x\n",
255                                          alg_key.l4port, alg_key.ip_address);
256
257         struct sip_alg_table_entry *new_alg_data =
258                         retrieve_sip_alg_entry(&alg_key);
259
260         if (new_alg_data) {
261                 if (ALG_DEBUG)
262                         printf("sip_alg_entry exists ip%x, port %d\n",
263                                                  alg_key.ip_address, alg_key.l4port);
264                 return 0;
265         }
266
267         new_alg_data = NULL;
268         new_alg_data = (struct sip_alg_table_entry *)
269                         malloc(sizeof(struct sip_alg_table_entry));
270         if (new_alg_data == NULL) {
271                 printf("populate sip alg entry: allocation failed\n");
272                 return -1;
273         }
274
275         new_alg_data->l4port = portid;
276         new_alg_data->ip_address = ipaddr;
277         new_alg_data->l4port_type = port_type;
278         new_alg_data->sip_alg_call_direction = call_direction;
279         strcpy((char *)new_alg_data->sip_alg_call_id, (char *)sip_call_id);
280         new_alg_data->filler1 = 0;
281         new_alg_data->filler2 = 0;
282         new_alg_data->filler3 = 0;
283
284         ret = rte_hash_add_key(sip_alg_hash_table, &alg_key);
285         if (ret < 0) {
286                 printf("populate sip - rte_hash_add_key_data ERROR %d\n", ret);
287                 free(new_alg_data);
288                 return -1;
289         }
290
291         sip_alg_table[ret] = new_alg_data;
292
293         if (ALG_DEBUG) {
294                 printf("SIP_ALG: table update - ip=%x on port=%d ret=%d\n",
295                                          alg_key.ip_address, portid, ret);
296         }
297         return 0;
298 }
299
300 int sip_alg_dpi(struct rte_mbuf *pkt, enum pkt_dir pkt_direction,
301                 uint32_t modIp, uint16_t modL4Port,
302                 uint32_t pubIp, uint16_t pubL4Port,
303                 uint16_t modRtpPort, uint16_t modRtcpPort)
304 {
305         uint16_t msgType = 0;
306         enum sip_alg_call_direction call_direction = 0;
307         uint32_t ip_address = 0;
308         uint16_t port = 0;
309         int ret = 0;
310         struct ipv4_hdr *ip_h;
311         struct ether_hdr *eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
312         struct udp_hdr *udp_h;
313         char *pSipMsg = NULL;
314         struct sip_alg_table_entry *sip_alg_entry;
315         char *sip_call_id = NULL;
316         int pos = 0;
317         struct sip_alg_key alg_key;
318         uint16_t diffModSipLen = 0;
319
320         ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
321         udp_h = (struct udp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
322         pSipMsg = ((char *)udp_h + sizeof(struct udp_hdr));
323
324         if (ALG_DEBUG) {
325         printf("%s: packet length(%u), buffer length(%u)\n", __func__,
326                 rte_pktmbuf_pkt_len(pkt), pkt->buf_len);
327         printf("%s: last segment addr(%p %p)\n", __func__,
328                 rte_pktmbuf_lastseg(pkt), pkt);
329         printf("%s: data len(%u, %u)\n", __func__, rte_pktmbuf_data_len(pkt),
330                 rte_pktmbuf_data_len(rte_pktmbuf_lastseg(pkt)));
331         printf("%s: buffer addr(%p), data_off(%u), nb_segs(%u)\n", __func__,
332                 pkt->buf_addr, pkt->data_off, pkt->nb_segs);
333         }
334
335         if (IS_STRING_SAME(pSipMsg, SIP_ALG_INVITE)) {
336                 /* find the call id position in the message */
337                 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CALLID, &pos, 0) ==
338                                 TRUE)
339                         sip_call_id =
340                                         getSipCallIdStr(pSipMsg + pos +
341                                                         TAG_TO_DATAPOS(SIP_ALG_CALLID));
342                         if (!sip_call_id) {
343                                 printf("sip_call_id returned is NULL\n");
344                                 return 0;
345                         }
346
347                 if (ALG_DEBUG)
348                         printf("sipalgdpi: %d call id %s\n", __LINE__,
349                                                  sip_call_id);
350
351                 if (pkt_direction == PRIVATE) {
352                         call_direction = SIP_CALL_OUTGOING;
353                         ip_address = rte_bswap32(ip_h->src_addr);
354                         port = rte_bswap16(udp_h->src_port);
355                 } else if (pkt_direction == PUBLIC) {
356                         call_direction = SIP_CALL_INCOMING;
357                         ip_address = pubIp;
358                         port = pubL4Port;
359                 }
360
361                 if (ALG_DEBUG)
362                         printf("0=>sip_alg_dpi: pkt_dir(%d), call_dir(%d), "
363                                                 "ipaddr(%x) port(%x)\n",
364                                          pkt_direction, call_direction, ip_address, port);
365
366                 /* add 3 entries in ALG table for SIP, RTP, RTCP */
367                 ret = populate_sip_alg_entry(ip_address, port,
368                                                          sip_call_id, call_direction,
369                                                          SIP_UDP);
370                 if (ret < 0) {
371                         printf("sipalgdpi:populate SIP alg UDP entry failed\n");
372                         return 0;
373                 }
374                 if (modRtpPort != 0) {
375                         ret = populate_sip_alg_entry(ip_address, modRtpPort,
376                                                                  sip_call_id,
377                                                                  call_direction, SIP_RTP);
378                         if (ret < 0) {
379                                 printf("sipalgdpi: "
380                                         "populate SIP alg entry RTP failed\n");
381                                 return 0;
382                         }
383                 }
384                 if (modRtcpPort != 0) {
385                         ret = populate_sip_alg_entry(ip_address, modRtcpPort,
386                                                                  sip_call_id,
387                                                                  call_direction, SIP_RTCP);
388                         if (ret < 0) {
389                                 printf("sipalgdpi: "
390                                 "populate SIP alg entry RTCP failed\n");
391                                 return 0;
392                         }
393                 }
394
395 /* Call ALG packet process function for checking & payload modification */
396                 pSipMsg =
397                                 sip_alg_process(pkt, pkt_direction, call_direction,
398                                                 SIP_ALG_INVITE_MSGTYPE, modIp, modL4Port, 0,
399                                                 0, modRtpPort, modRtcpPort, &diffModSipLen);
400         } else {
401         /*
402          * not SIP INVITE, could be SIP response 200 OK invite, 100 trying,
403          * 180 ringing or BYE or 200 OK BYe
404          */
405                 /* retrieve ALG entry from SIP ALG table */
406                 if (pkt_direction == PRIVATE) {
407                         alg_key.ip_address = rte_bswap32(ip_h->src_addr);
408                         alg_key.l4port = rte_bswap16(udp_h->src_port);
409                 } else {
410                         alg_key.ip_address = pubIp;
411                         alg_key.l4port = pubL4Port;
412                 }
413
414                 alg_key.filler1 = 0;
415                 alg_key.filler2 = 0;
416                 sip_alg_entry = retrieve_sip_alg_entry(&alg_key);
417
418                 if (ALG_DEBUG) {
419                         printf("%s: sip_alg_entry_ptr(%p)\n", __func__,
420                                                  sip_alg_entry);
421                         printf("1=>%s: pkt_dir(%d), modIp(%x),modL4Port(%x), "
422                 "modRtpPort(%x), modRtcpPort(%x), pubIp(%x), pubL4Port(%x)\n",
423                                          __func__, pkt_direction, modIp, modL4Port,
424                                          modRtpPort, modRtcpPort, pubIp, pubL4Port);
425                 }
426
427                 if (sip_alg_entry) {
428                         call_direction = sip_alg_entry->sip_alg_call_direction;
429                         if (IS_STRING_SAME(pSipMsg, SIP_ALG_BYE) ||
430                                         IS_STRING_SAME(pSipMsg, SIP_ALG_CANCEL)) {
431                                 msgType = SIP_ALG_BYE_MSGTYPE;
432
433                                 goto sipAlgProcess;
434                         } else if (IS_STRING_SAME(pSipMsg, SIP_ALG_ACK)) {
435                                 msgType = SIP_ALG_ACK_MSGTYPE;
436
437                                 goto sipAlgProcess;
438                         }
439
440                         pSipMsg += 8;
441                 /* checking if its OK or Trying or Ringing */
442                         if (IS_STRING_SAME(pSipMsg, SIP_ALG_200_OK)) {
443                         /* check CSEQ. Based on that update the msg type */
444                                 if (natSipAlgMsgFieldPos
445                                                 (pSipMsg, SIP_ALG_CSEQ, &pos, 0) == TRUE) {
446                                         char *pBye;
447
448                                         pBye =
449                                                         pSipMsg + pos +
450                                                         TAG_TO_DATAPOS(SIP_ALG_CSEQ);
451                                         SKIP_SPACES(pBye);
452                                         /* skip the number field */
453                                         while (*pBye != ' ')
454                                                 pBye++;
455                                         SKIP_SPACES(pBye);
456                                         if (IS_STRING_SAME(pBye, SIP_ALG_BYE)
457                                                         ||
458                                                         (IS_STRING_SAME
459                                                          (pBye, SIP_ALG_CANCEL)))
460                                                 msgType =
461                                                                 SIP_ALG_200_OK_BYE_MSGTYPE;
462
463                                         else
464                                                 msgType =
465                                                         SIP_ALG_200_OK_INVITE_MSGTYPE;
466                                 }
467                         } else if (IS_STRING_SAME(pSipMsg, SIP_ALG_TRYING) ||
468                                          IS_STRING_SAME(pSipMsg, SIP_ALG_RINGING)) {
469                                 msgType = SIP_ALG_TRYING_RINGING_MSGTYPE;
470                         }
471
472  sipAlgProcess:
473                         if (ALG_DEBUG)
474                                 printf("2=>%s: pkt_dir(%d), call_dir(%d), "
475                                 "msgType(%d), modIp(%x), modL4Port(%x), "
476                                 " modRtpPort(%x), modRtcpPort(%x)\n",
477                                                  __func__, pkt_direction, call_direction,
478                                                  msgType, modIp, modL4Port, modRtpPort,
479                                                  modRtcpPort);
480                         /* Call SIP alg processing for further processing. */
481                         pSipMsg =
482                                         sip_alg_process(pkt, pkt_direction, call_direction,
483                                                         msgType, modIp, modL4Port, pubIp,
484                                                         pubL4Port, modRtpPort, modRtcpPort,
485                                                         &diffModSipLen);
486                 } else
487                         pSipMsg = NULL;
488         }
489
490         if (ALG_DEBUG)
491                 printf("%s: Before IP total length(%u), udp length(%u)\n", __func__,
492                 rte_bswap16(ip_h->total_length), rte_bswap16(udp_h->dgram_len));
493         /*
494          * need to modify mbuf & modified length of payload in the IP/UDP
495          * header length fields and return to CGNAT for transmitting
496          */
497         uint16_t len = 0;
498         if (diffModSipLen > 0) {
499                 len = rte_bswap16(udp_h->dgram_len);
500                 len += diffModSipLen;
501                 udp_h->dgram_len = rte_bswap16(len);
502
503                 len = rte_bswap16(ip_h->total_length);
504                 len += diffModSipLen;
505                 ip_h->total_length = rte_bswap16(len);
506
507                 if (rte_pktmbuf_append(pkt, diffModSipLen) == NULL)
508                         printf("%s: pktmbuf_append returns NULL", __func__);
509
510         }
511
512         if (ALG_DEBUG)
513                 printf("%s: After IP total length(%u), udp length(%u), "
514                 "diffModSipLen(%u)\n", __func__,
515                 rte_bswap16(ip_h->total_length),
516                 rte_bswap16(udp_h->dgram_len),
517                 diffModSipLen);
518
519         if (pSipMsg != NULL)
520                 return 1;
521         else
522                 return 0;
523 }
524
525 char *sip_alg_process(struct rte_mbuf *pkt, uint16_t pkt_direction,
526                                         uint16_t call_direction, uint16_t msgType, uint32_t modIp,
527                                         uint16_t modL4Port, uint32_t pubIp, uint16_t pubL4Port,
528                                         uint16_t modRtpPort, uint16_t modRtcpPort,
529                                         uint16_t *diffModSipLen)
530 {
531         struct ipv4_hdr *ip_h;
532         struct ether_hdr *eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
533         struct udp_hdr *udp_h;
534         char *pSipMsg, *pStr, *pEndPtr;
535         int pos;
536         /* diff between old & new modified field len */
537         uint32_t diffLen, addrPortLen;
538         int sdpMsgLen = 0;
539         int sip_msg_len = 0;
540
541         ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
542         udp_h = (struct udp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
543         pSipMsg = ((char *)udp_h + sizeof(struct udp_hdr));
544         char *pTmpSipMsg = pSipMsg;
545         char *pStartSipMsg = pSipMsg;
546
547         sip_msg_len =
548                         rte_bswap16(ip_h->total_length) - sizeof(struct ipv4_hdr) -
549                         sizeof(struct udp_hdr);
550
551         if (natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0) ==
552                         TRUE)
553                 pTmpSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN));
554         else {
555                 printf("sip_alg_process: Invalid Content Length\n");
556                 return NULL;
557         }
558
559         SKIP_SPACES(pTmpSipMsg);
560         int sdpDataLen = strtol(pTmpSipMsg, &pStr, 10);
561
562         natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_DOUBLE_CRLF, &pos, 0);
563         pTmpSipMsg += (pos + strlen(SIP_ALG_DOUBLE_CRLF));
564
565         if (sdpDataLen != 0)
566                 if (natSipAlgMsgFieldPos
567                                 (pTmpSipMsg, SIP_ALG_REMOTE_PARTY_ID, &pos, 0) == TRUE) {
568                         pTmpSipMsg += pos + strlen(SIP_ALG_REMOTE_PARTY_ID);
569                         /* move further to CRLF which is the end of SIP msg */
570                         natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
571                                                                  SIP_ALG_DOUBLE_CRLF, &pos,
572                                                                  0);
573                         pTmpSipMsg += (pos + strlen(SIP_ALG_DOUBLE_CRLF));
574                 }
575
576         int sipMsgLen = (pTmpSipMsg - pSipMsg);
577
578         if ((sipMsgLen + sdpDataLen) > strlen(pSipMsg))
579                 return NULL;
580
581         char *pSipMsgEnd = pSipMsg + sipMsgLen + sdpDataLen;
582
583         if (ALG_DEBUG)
584                 printf("%s: pSipMsg: %p, pSipMsgEnd: %p, sipMsgLen: %d, "
585                                 "sdpDataLen: %d totalSipMsgLen: %d\n",
586                                  __func__, pSipMsg, pSipMsgEnd, sipMsgLen, sdpDataLen,
587                                  sip_msg_len);
588
589         if (call_direction == SIP_CALL_OUTGOING) {
590                 if ((msgType == SIP_ALG_INVITE_MSGTYPE)
591                                 || (msgType == SIP_ALG_ACK_MSGTYPE)) {
592                         /* Get to Via field IP address/Port to modify */
593                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
594                                         == TRUE) {
595                                 /* advance to IP/Port string */
596                                 pSipMsg +=
597                                                 (pos + strlen(SIP_ALG_VIA) +
598                                                  SIP_ALG_VIA_FIELD_IPADDR);
599                                 pTmpSipMsg = pSipMsg;
600                                 /* move pTmp to next field */
601                                 natSipAlgMsgFieldPos(pTmpSipMsg,
602                                                                  SIP_ALG_SEMICOLON, &pos,
603                                                                  0);
604                                 pTmpSipMsg += pos;
605                                 addrPortLen = pTmpSipMsg - pSipMsg;
606                         } else {
607                                 printf("sip_alg_process; No valid VIA field\n");
608                                 return NULL;
609                         }
610                         /* Modify VIA field IP addr:port in payload */
611                         pSipMsg =
612                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
613                                                                  addrPortLen,
614                                                                  &diffLen, modIp,
615                                                                  modL4Port,
616                                                                  ADDRESS_PORT_STRING);
617
618                         *diffModSipLen += diffLen;
619 /* increase the overall diff between old & mod sip msg */
620
621                         /* Advance to "From" field IP addr in payload */
622                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
623                                         == TRUE) {
624                                 pSipMsg += pos; /* Moving to "From" */
625                                 /* advance to IP/Port string */
626                                 pTmpSipMsg = pSipMsg;
627 /* move pTmpSipMsg to str ">" which is end of add:port string */
628                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
629                                                                  &pos, 0);
630                                 pTmpSipMsg += pos;
631                                 diffLen = pTmpSipMsg - pSipMsg;
632 /* find "@" from "From" string to ">" string which is start of "addr:port" */
633                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
634                                                                  0);
635                                 pSipMsg += pos + 1;
636 /* now its pointing to start of From field "address:port" */
637                                 addrPortLen = pTmpSipMsg - pSipMsg;
638                         } else {
639                                 printf
640                                                 ("sip_alg_process; No valid From field\n");
641                                 return NULL;
642                         }
643                         /* Modify "From" field "addr:port" in payload */
644                         pSipMsg =
645                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
646                                                                  addrPortLen,
647                                                                  &diffLen, modIp,
648                                                                  modL4Port,
649                                                                  ADDRESS_PORT_STRING);
650
651                         *diffModSipLen += diffLen;
652 /* increase the overall diff between old & mod sip msg */
653
654                         /* Advance to Call id field */
655                         if (natSipAlgMsgFieldPos
656                                         (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
657                                 pSipMsg += pos;
658 /* moving it to start of string "Call-ID" */
659                                 pTmpSipMsg = pSipMsg;
660                                 /* move tmpSipMsg to next field */
661                                 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
662                                                                          SIP_ALG_CRLF, &pos,
663                                                                          0);
664                                 pTmpSipMsg += pos;
665                                 diffLen = pTmpSipMsg - pSipMsg;
666                 /* Move pSipMsg to start of Call id "IP addr" string */
667                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
668                                                                  0);
669                                 pSipMsg += pos + 1;
670                                 addrPortLen = pTmpSipMsg - pSipMsg;
671                         } else {
672                                 printf("sip_alg_process; "
673                                         " No valid Call Id field\n");
674                                 return NULL;
675                         }
676                         /* Modify "Call-id" field "addr:port" in payload */
677 /* L4 port input is made as 0 as its only addr string modification */
678                         pSipMsg =
679                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
680                                                                  addrPortLen,
681                                                                  &diffLen, modIp, 0,
682                                                                  ADDRESS_PORT_STRING);
683
684                         *diffModSipLen += diffLen;
685
686                         /* Advance to "Contact" field */
687                         if (natSipAlgMsgFieldPos
688                                         (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) {
689                                 pSipMsg += pos;
690                                 /* move tmpMsg to CRLF */
691                                 pTmpSipMsg = pSipMsg;
692                                 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
693                                                                          SIP_ALG_CRLF, &pos,
694                                                                          0);
695                                 pTmpSipMsg += pos;
696                                 /* move sipMsg to addr:port string */
697                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
698                                                                  0);
699                                 pSipMsg += pos + 1;
700                                 addrPortLen = pTmpSipMsg - pSipMsg;
701
702                         } else {
703                                 printf("sip_alg_process; "
704                                         "No valid Call Id field\n");
705                                 return NULL;
706                         }
707                         /* Modify "Contact" field "addr:port" in payload */
708                         pSipMsg =
709                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
710                                                                  addrPortLen,
711                                                                  &diffLen, modIp,
712                                                                  modL4Port,
713                                                                  ADDRESS_PORT_STRING);
714
715                         *diffModSipLen += diffLen;
716
717                         if (msgType == SIP_ALG_INVITE_MSGTYPE) {
718 /* Advance to check content type & get content length (SDP length) */
719                                 if (natSipAlgMsgFieldPos
720                                                 (pSipMsg, SIP_ALG_CONTYPE, &pos,
721                                                  0) == TRUE) {
722                                         pSipMsg +=
723                                                         (pos +
724                                                          TAG_TO_DATAPOS(SIP_ALG_CONTYPE));
725                                         SKIP_SPACES(pSipMsg);
726                         /*check the application/sdp type, if not, exit */
727                                         if (!IS_STRING_SAME
728                                                         (pSipMsg, SIP_ALG_APPSDP)) {
729                                                 printf("sip_alg_process "
730                                                 "Invalid Content type\n");
731                                                 return NULL;
732                                         }
733                                 } else {
734                                         printf("sip_alg_process; "
735                                                 "No valid Content field\n");
736                                         return NULL;
737                                 }
738
739                                 /* get the SDP content length */
740                                 natSipAlgMsgFieldPos(pSipMsg,
741                                                                  SIP_ALG_CONTENT_LEN, &pos,
742                                                                  0);
743                                 pSipMsg +=
744                                                 (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN));
745                                 SKIP_SPACES(pSipMsg);
746                                 sdpMsgLen = strtol(pSipMsg, &pEndPtr, 10);
747                                 if (!sdpMsgLen) {
748 /* if ACK message, SDP content wont be there.go to ALG process complete */
749                                         if (msgType == SIP_ALG_ACK_MSGTYPE)
750                                                 goto sipAlgProcessExit;
751
752                                         printf("sip_alg_process - "
753                                                 "sdpMsgLen is 0\n");
754                                         return NULL;
755                                 }
756
757                                 /* Advance to SDP data message Owner address */
758                                 if (natSipAlgMsgFieldPos
759                                                 (pSipMsg, SIP_ALG_OWNER, &pos,
760                                                  0) == TRUE) {
761                                         pSipMsg += pos;
762                         /* at start of owner string "o=" */
763                                         pTmpSipMsg = pSipMsg;
764                                         /* move tmmsg to CRLF of owner field */
765                                         natSipAlgMsgFieldPosFindCrlf(pSipMsg,
766                                                                          SIP_ALG_CRLF,
767                                                                          &pos,
768                                                                          0);
769                                         pTmpSipMsg += pos;
770 /* start of CRLF "/r/n" */
771 /* move pSipMsg to IP address string in owner field */
772                                         natSipAlgMsgFieldPos(pSipMsg,
773                                                                          SIP_ALG_IPV4, &pos,
774                                                                          0);
775                                         pSipMsg += (pos + strlen(SIP_ALG_IPV4));
776                                         SKIP_SPACES(pSipMsg);
777 /* after skipping spaces, pSip at start of addr */
778                                         addrPortLen = pTmpSipMsg - pSipMsg;
779                                 } else {
780                                         printf("sip_alg_processing: "
781                                                 "Invalid Owner field\n");
782                                         return NULL;
783                                 }
784 /* Modify "Owner" field "addr" in payload.  Input L4 port as 0 */
785                                 pSipMsg =
786                                                 natSipAlgModifyPayloadAddrPort(pSipMsg,
787                                                                          &pSipMsgEnd,
788                                                                          addrPortLen,
789                                                                          &diffLen,
790                                                                          modIp, 0,
791                                                                  ADDRESS_PORT_STRING);
792
793                                 *diffModSipLen += diffLen;
794                                 sdpMsgLen += diffLen;
795 /* need to adjust the SDP msg len as modification done. */
796
797 /* Advance to Connection information to modify IP address */
798                                 if (natSipAlgMsgFieldPos
799                                                 (pSipMsg, SIP_ALG_CONN, &pos,
800                                                  0) == TRUE) {
801                                         pSipMsg += pos;
802                                         pTmpSipMsg = pSipMsg;
803                                         /* move tmmsg to CRLF of owner field */
804                                         natSipAlgMsgFieldPosFindCrlf(pSipMsg,
805                                                                          SIP_ALG_CRLF,
806                                                                                  &pos,
807                                                                                  0);
808                                         pTmpSipMsg += pos;
809                         /* start of CRLF "/r/n" */
810                         /* move pSipMsg to IP address string in owner field */
811                                         natSipAlgMsgFieldPos(pSipMsg,
812                                                                          SIP_ALG_IPV4, &pos,
813                                                                          0);
814                                         pSipMsg += (pos + strlen(SIP_ALG_IPV4));
815                                         SKIP_SPACES(pSipMsg);
816 /* after skipping spaces, pSip at start of addr */
817                                         addrPortLen = pTmpSipMsg - pSipMsg;
818                                 } else {
819                                         printf("sip_alg_processing: "
820                                                 "Invalid Owner field\n");
821                                         return NULL;
822                                 }
823 /* Modify "Connection" field "addr" in payload.  Input L4 port as 0 */
824                                 pSipMsg =
825                                                 natSipAlgModifyPayloadAddrPort(pSipMsg,
826                                                                          &pSipMsgEnd,
827                                                                          addrPortLen,
828                                                                          &diffLen,
829                                                                          modIp, 0,
830                                                                  ADDRESS_PORT_STRING);
831
832                                 *diffModSipLen += diffLen;
833                                 sdpMsgLen += diffLen;
834 /* need to adjust the SDP msg len as modification done. */
835
836                                 /* Advance to RTP audio port */
837                                 if (natSipAlgMsgFieldPos
838                                                 (pSipMsg, SIP_ALG_AUDIO, &pos,
839                                                  0) == TRUE) {
840                                         pSipMsg +=
841                                                         (pos +
842                                                          TAG_TO_DATAPOS(SIP_ALG_AUDIO));
843                                         SKIP_SPACES(pSipMsg);
844                                         pTmpSipMsg = pSipMsg;
845                                         natSipAlgMsgFieldPosFindSpace
846                                                         (pTmpSipMsg, SIP_ALG_SPACE, &pos,
847                                                          0);
848                                         pTmpSipMsg += pos;
849                                         addrPortLen = pTmpSipMsg - pSipMsg;
850                                 }
851
852 /* Modify "RTP Audio" port in payload. pass pub_ip as 0. */
853                                 pSipMsg =
854                                                 natSipAlgModifyPayloadAddrPort(pSipMsg,
855                                                                          &pSipMsgEnd,
856                                                                          addrPortLen,
857                                                                          &diffLen, 0,
858                                                                          modRtpPort,
859                                                                          PORT_STRING);
860
861                                 *diffModSipLen += diffLen;
862                                 sdpMsgLen += diffLen;
863 /* need to adjust the SDP msg len as modification done. */
864
865                                 /* Advance to RTCP control port, if its there */
866                                 if (natSipAlgMsgFieldPos
867                                                 (pSipMsg, SIP_ALG_RTCP, &pos,
868                                                  0) == TRUE) {
869                                         pSipMsg +=
870                                                         (pos +
871                                                          TAG_TO_DATAPOS(SIP_ALG_RTCP));
872                                         SKIP_SPACES(pSipMsg);
873                                         pTmpSipMsg = pSipMsg;
874                                         natSipAlgMsgFieldPosFindSpace
875                                                         (pTmpSipMsg, SIP_ALG_SPACE, &pos,
876                                                          0);
877                                         pTmpSipMsg += pos;
878                                         addrPortLen = pTmpSipMsg - pSipMsg;
879
880 /* Modify "RTP Audio" port in payload. pass pub_ip as 0. */
881                                         pSipMsg =
882                                                         natSipAlgModifyPayloadAddrPort
883                                                         (pSipMsg, &pSipMsgEnd, addrPortLen,
884                                                          &diffLen, 0, modRtcpPort,
885                                                          PORT_STRING);
886
887                                         *diffModSipLen += diffLen;
888                                         sdpMsgLen += diffLen;
889 /* need to adjust the SDP msg len as modification done. */
890                                 }
891                         }
892 /* with this SIP payload modification is complete for outbound invite message */
893                 } else if ((msgType == SIP_ALG_TRYING_RINGING_MSGTYPE)
894                                  || (msgType == SIP_ALG_200_OK_INVITE_MSGTYPE)) {
895                         /* Get to Via field IP address/Port to modify */
896                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
897                                         == TRUE) {
898                                 /* advance to IP/Port string */
899                                 pSipMsg +=
900                                                 (pos + strlen(SIP_ALG_VIA) +
901                                                  SIP_ALG_VIA_FIELD_IPADDR);
902                                 pTmpSipMsg = pSipMsg;
903                                 /* move pTmp to next field */
904                                 natSipAlgMsgFieldPos(pTmpSipMsg,
905                                                                  SIP_ALG_SEMICOLON, &pos,
906                                                                  0);
907                                 pTmpSipMsg += pos;
908                                 addrPortLen = pTmpSipMsg - pSipMsg;
909                         } else {
910                                 printf("sip_alg_process; No valid VIA field\n");
911                                 return NULL;
912                         }
913                         /* Modify VIA field IP addr:port in payload */
914                         pSipMsg =
915                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
916                                                                  addrPortLen,
917                                                                  &diffLen, modIp,
918                                                                  modL4Port,
919                                                                  ADDRESS_PORT_STRING);
920                         *diffModSipLen = diffLen;
921
922                         /* Advance to "From" field IP addr in payload */
923                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
924                                         == TRUE) {
925                                 pSipMsg += pos; /* Moving to "From" */
926                                 /* advance to IP/Port string */
927                                 pTmpSipMsg = pSipMsg;
928 /* move pTmpSipMsg to str ">" which is end of add:port string */
929                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
930                                                                  &pos, 0);
931                                 pTmpSipMsg += pos;
932                                 //diffLen = pTmpSipMsg - pSipMsg;
933 /* find "@" from "From" string to ">" string which is start of "addr:port" */
934                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
935                                                                  0);
936                                 pSipMsg += pos + 1;
937 /* now its pointing to start of From field "address:port" */
938                                 addrPortLen = pTmpSipMsg - pSipMsg;
939                         } else {
940                                 printf
941                                                 ("sip_alg_process; No valid From field\n");
942                                 return NULL;
943                         }
944                         /* Modify "From" field "addr:port" in payload */
945                         pSipMsg =
946                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
947                                                                  addrPortLen,
948                                                                  &diffLen, modIp,
949                                                                  modL4Port,
950                                                                  ADDRESS_PORT_STRING);
951
952                         *diffModSipLen += diffLen;
953 /* increase the overall diff between old & mod sip msg */
954
955                         /* Advance to Call id field */
956                         if (natSipAlgMsgFieldPos
957                                         (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
958                                 pSipMsg += pos;
959 /* moving it to start of string "Call-ID" */
960                                 pTmpSipMsg = pSipMsg;
961                                 /* move tmpSipMsg to next field */
962                                 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
963                                                                          SIP_ALG_CRLF, &pos,
964                                                                          0);
965                                 pTmpSipMsg += pos;
966                                 //diffLen = pTmpSipMsg - pSipMsg;
967                 /* Move pSipMsg to start of Call id "IP addr" string */
968                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
969                                                                  0);
970                                 pSipMsg += pos + 1;
971                                 addrPortLen = pTmpSipMsg - pSipMsg;
972                         } else {
973                                 printf("sip_alg_process; "
974                                         "No valid Call Id field\n");
975                                 return NULL;
976                         }
977                         /* Modify "Call-id" field "addr" in payload */
978 /* L4 port input is made as 0 as its only addr string modification */
979                         pSipMsg =
980                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
981                                                                  addrPortLen,
982                                                                  &diffLen, modIp, 0,
983                                                                  ADDRESS_PORT_STRING);
984
985                         *diffModSipLen += diffLen;
986
987                 } else if (pkt_direction == PRIVATE
988                                  && msgType == SIP_ALG_BYE_MSGTYPE) {
989                         /* change via, from, call-id and contact field */
990
991                         /* Get to Via field IP address to modify */
992                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
993                                         == TRUE) {
994                                 /* advance to IP/Port string */
995                                 pSipMsg +=
996                                                 (pos + strlen(SIP_ALG_VIA) +
997                                                  SIP_ALG_VIA_FIELD_IPADDR);
998                                 pTmpSipMsg = pSipMsg;
999                                 /* move pTmp to next field */
1000                                 natSipAlgMsgFieldPos(pTmpSipMsg,
1001                                                                  SIP_ALG_SEMICOLON, &pos,
1002                                                                  0);
1003                                 pTmpSipMsg += pos;
1004                                 addrPortLen = pTmpSipMsg - pSipMsg;
1005                         } else {
1006                                 printf("sip_alg_process; No valid VIA field\n");
1007                                 return NULL;
1008                         }
1009                         /* Modify VIA field IP addr in payload */
1010                         pSipMsg =
1011                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1012                                                                  addrPortLen,
1013                                                                  &diffLen, modIp, 0,
1014                                                                  ADDRESS_PORT_STRING);
1015                         *diffModSipLen = diffLen;
1016
1017                         /* Advance to "From" field IP addr in payload */
1018                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
1019                                         == TRUE) {
1020                                 pSipMsg += pos; /* Moving to "From" */
1021                                 /* advance to IP/Port string */
1022                                 pTmpSipMsg = pSipMsg;
1023 /* move pTmpSipMsg to str ">" which is end of add:port string */
1024                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1025                                                                  &pos, 0);
1026                                 pTmpSipMsg += pos;
1027                                 diffLen = pTmpSipMsg - pSipMsg;
1028 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1029                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1030                                                                  0);
1031                                 pSipMsg += pos + 1;
1032 /* now its pointing to start of From field "address:port" */
1033                                 addrPortLen = pTmpSipMsg - pSipMsg;
1034                         } else {
1035                                 printf
1036                                                 ("sip_alg_process; No valid From field\n");
1037                                 return NULL;
1038                         }
1039                         /* Modify "From" field "addr:port" in payload */
1040                         pSipMsg =
1041                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1042                                                                  addrPortLen,
1043                                                                  &diffLen, modIp,
1044                                                                  modL4Port,
1045                                                                  ADDRESS_PORT_STRING);
1046
1047                         *diffModSipLen += diffLen;
1048 /* increase the overall diff between old & mod sip msg */
1049
1050                         /* Advance to Call id field */
1051                         if (natSipAlgMsgFieldPos
1052                                         (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
1053                                 pSipMsg += pos;
1054 /* moving it to start of string "Call-ID" */
1055                                 pTmpSipMsg = pSipMsg;
1056                                 /* move tmpSipMsg to next field */
1057                                 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1058                                                                          SIP_ALG_CRLF, &pos,
1059                                                                          0);
1060                                 pTmpSipMsg += pos;
1061                                 diffLen = pTmpSipMsg - pSipMsg;
1062                 /* Move pSipMsg to start of Call id "IP addr" string */
1063                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1064                                                                  0);
1065                                 pSipMsg += pos + 1;
1066                                 addrPortLen = pTmpSipMsg - pSipMsg;
1067                         } else {
1068                                 printf("sip_alg_process; "
1069                                         "No valid Call Id field\n");
1070                                 return NULL;
1071                         }
1072                         /* Modify "Call-id" field "addr:port" in payload */
1073         /* L4 port input is made as 0 as its only addr string modification */
1074                         pSipMsg =
1075                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1076                                                                  addrPortLen,
1077                                                                  &diffLen, modIp, 0,
1078                                                                  ADDRESS_PORT_STRING);
1079
1080                         *diffModSipLen += diffLen;
1081
1082                         /* Advance to "Contact" field */
1083                         if (natSipAlgMsgFieldPos
1084                                         (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) {
1085                                 pSipMsg += pos;
1086                                 /* move tmpMsg to semicolon */
1087                                 pTmpSipMsg = pSipMsg;
1088                                 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1089                                         SIP_ALG_CRLF, &pos, 0);
1090                                 pTmpSipMsg += pos;
1091                                 /* move sipMsg to addr:port string */
1092                                 int flag = 0;
1093                                 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT,
1094                                                 &pos, 0) == FALSE)
1095                                         flag = 1;
1096
1097                                 if (flag)
1098                                         goto SipMsgAdvance2;
1099                                 pSipMsg += pos + 1;
1100                                 addrPortLen = pTmpSipMsg - pSipMsg;
1101
1102                         } else {
1103                                 printf("sip_alg_process; "
1104                                         "No valid Call Id field\n");
1105                                 return NULL;
1106                         }
1107                         /* Modify "Contact" field "addr:port" in payload */
1108                         pSipMsg =
1109                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1110                                                                  addrPortLen,
1111                                                                  &diffLen, modIp,
1112                                                                  modL4Port,
1113                                                                  ADDRESS_PORT_STRING);
1114
1115                         *diffModSipLen += diffLen;
1116                 } else if (pkt_direction == PUBLIC
1117                                  && msgType == SIP_ALG_BYE_MSGTYPE) {
1118                         /*
1119                          * Modify Bye URL (if its BYE), To field,
1120                          * Call-Id if call triggered from private, then modify
1121                          */
1122
1123                         /* need to modify address:Port in Bye message string. */
1124                         natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0);
1125                         pSipMsg += pos + 1;
1126                         pTmpSipMsg = pSipMsg;
1127                         natSipAlgMsgFieldPosFindSpace(pTmpSipMsg, SIP_ALG_SPACE,
1128                                                                         &pos, 0);
1129                         pTmpSipMsg += pos;
1130                         addrPortLen = pTmpSipMsg - pSipMsg;
1131                         /* modify the "addr:port" in Bye message line */
1132                         pSipMsg =
1133                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1134                                                                  addrPortLen,
1135                                                                  &diffLen, modIp,
1136                                                                  modL4Port,
1137                                                                  ADDRESS_PORT_STRING);
1138                         *diffModSipLen += diffLen;
1139 /* increase the overall diff between old & mod sip msg */
1140
1141                         /* Advance to 'To" field */
1142                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1143                                         == TRUE) {
1144                                 pSipMsg += pos;
1145                                 pTmpSipMsg = pSipMsg;
1146                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1147                                                                  &pos, 0);
1148                                 pTmpSipMsg += pos;
1149                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1150                                                                  0);
1151                                 pSipMsg += pos + 1;
1152                                 addrPortLen = pTmpSipMsg - pSipMsg;
1153                                 pSipMsg =
1154                                                 natSipAlgModifyPayloadAddrPort(pSipMsg,
1155                                                                          &pSipMsgEnd,
1156                                                                          addrPortLen,
1157                                                                          &diffLen,
1158                                                                          modIp,
1159                                                                          modL4Port,
1160                                                                  ADDRESS_PORT_STRING);
1161                                 *diffModSipLen += diffLen;
1162 /* increase the overall diff between old & mod sip msg */
1163                         }
1164
1165                         /* check for Call-Id. */
1166                         if (natSipAlgMsgFieldPos
1167                                         (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
1168                                 pSipMsg += pos;
1169 /* moving it to start of string "Call-ID" */
1170                                 pTmpSipMsg = pSipMsg;
1171                                 /* move tmpSipMsg to next field */
1172                                 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1173                                                                          SIP_ALG_CRLF, &pos,
1174                                                                          0);
1175                                 pTmpSipMsg += pos;
1176                                 //diffLen = pTmpSipMsg - pSipMsg;
1177                 /* Move pSipMsg to start of Call id "IP addr" string */
1178                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1179                                                                  0);
1180                                 pSipMsg += pos + 1;
1181                                 addrPortLen = pTmpSipMsg - pSipMsg;
1182                         } else {
1183                                 printf("sip_alg_process; "
1184                                         "No valid Call Id field\n");
1185                                 return NULL;
1186                         }
1187                         /* Modify "Call-id" field "addr" in payload */
1188         /* L4 port input is made as 0 as its only addr string modification */
1189                         pSipMsg =
1190                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1191                                                                  addrPortLen,
1192                                                                  &diffLen, modIp, 0,
1193                                                                  ADDRESS_PORT_STRING);
1194
1195                         *diffModSipLen += diffLen;
1196                 } else if (pkt_direction == PRIVATE
1197                                  && (msgType == SIP_ALG_200_OK_BYE_MSGTYPE)) {
1198                         /*
1199                          *  Need to modify To field, Call-Id,
1200                          * Contact if call triggered from private, then modify
1201                          */
1202                 /* Get to To field IP address to modify */
1203                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1204                                         == TRUE) {
1205                                 pSipMsg += pos; /* Moving to "From" */
1206                                 /* advance to IP/Port string */
1207                                 pTmpSipMsg = pSipMsg;
1208 /* move pTmpSipMsg to str ">" which is end of add:port string */
1209                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1210                                                                  &pos, 0);
1211                                 pTmpSipMsg += pos;
1212                                 diffLen = pTmpSipMsg - pSipMsg;
1213 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1214                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1215                                                                  0);
1216                                 pSipMsg += pos + 1;
1217 /* now its pointing to start of From field "address:port" */
1218                                 addrPortLen = pTmpSipMsg - pSipMsg;
1219                         } else {
1220                                 printf
1221                                                 ("sip_alg_process; no valid from field\n");
1222                                 return NULL;
1223                         }
1224                         /* Modify "From" field "addr:port" in payload */
1225                         pSipMsg =
1226                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1227                                                                  addrPortLen,
1228                                                                  &diffLen, modIp,
1229                                                                  modL4Port,
1230                                                                  ADDRESS_PORT_STRING);
1231
1232                         *diffModSipLen = diffLen;
1233 /* increase the overall diff between old & mod sip msg */
1234
1235                         /* Advance to "Contact" field */
1236                         if (natSipAlgMsgFieldPos
1237                                         (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) {
1238                                 pSipMsg += pos;
1239                                 /* move tmpMsg to CRLF */
1240                                 pTmpSipMsg = pSipMsg;
1241                                 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1242                                                                          SIP_ALG_CRLF, &pos,
1243                                                                          0);
1244                                 pTmpSipMsg += pos;
1245                                 /* move sipMsg to addr:port string */
1246                                 int flag = 0;
1247                                 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT,
1248                                         &pos, 0) == FALSE)
1249                                         flag = 1;
1250
1251                                 if (flag)
1252                                         goto SipMsgAdvance2;
1253                                 pSipMsg += pos + 1;
1254                                 addrPortLen = pTmpSipMsg - pSipMsg;
1255                         } else {
1256                                 printf("sip_alg_process; "
1257                                         "No valid Call Id field\n");
1258                                 return NULL;
1259                         }
1260                         /* Modify "Contact" field "addr:port" in payload */
1261                         pSipMsg =
1262                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1263                                                                  addrPortLen,
1264                                                                  &diffLen, modIp,
1265                                                                  modL4Port,
1266                                                                  ADDRESS_PORT_STRING);
1267
1268                         *diffModSipLen += diffLen;
1269                 } else if (pkt_direction == PUBLIC
1270                                  && (msgType == SIP_ALG_200_OK_BYE_MSGTYPE)) {
1271                         /* change via and from field, call-id field */
1272
1273                         /* Get to Via field IP address to modify */
1274                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
1275                                         == TRUE) {
1276                                 /* advance to IP/Port string */
1277                                 pSipMsg +=
1278                                                 (pos + strlen(SIP_ALG_VIA) +
1279                                                  SIP_ALG_VIA_FIELD_IPADDR);
1280                                 pTmpSipMsg = pSipMsg;
1281                                 /* move pTmp to next field */
1282                                 natSipAlgMsgFieldPos(pTmpSipMsg,
1283                                                                  SIP_ALG_SEMICOLON, &pos,
1284                                                                  0);
1285                                 pTmpSipMsg += pos;
1286                                 addrPortLen = pTmpSipMsg - pSipMsg;
1287                         } else {
1288                                 printf("sip_alg_process; No valid VIA field\n");
1289                                 return NULL;
1290                         }
1291                         /* Modify VIA field IP addr in payload */
1292                         pSipMsg =
1293                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1294                                                                  addrPortLen,
1295                                                                  &diffLen, modIp, 0,
1296                                                                  ADDRESS_PORT_STRING);
1297                         *diffModSipLen = diffLen;
1298
1299                         /* Advance to "From" field IP addr in payload */
1300                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
1301                                         == TRUE) {
1302                                 pSipMsg += pos; /* Moving to "From" */
1303                                 /* advance to IP/Port string */
1304                                 pTmpSipMsg = pSipMsg;
1305 /* move pTmpSipMsg to str ">" which is end of add:port string */
1306                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1307                                                                  &pos, 0);
1308                                 pTmpSipMsg += pos;
1309                                 diffLen = pTmpSipMsg - pSipMsg;
1310 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1311                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1312                                                                  0);
1313                                 pSipMsg += pos + 1;
1314 /* now its pointing to start of From field "address:port" */
1315                                 addrPortLen = pTmpSipMsg - pSipMsg;
1316                         } else {
1317                                 printf
1318                                                 ("sip_alg_process; No valid From field\n");
1319                                 return NULL;
1320                         }
1321                         /* Modify "From" field "addr:port" in payload */
1322                         pSipMsg =
1323                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1324                                                                  addrPortLen,
1325                                                                  &diffLen, modIp,
1326                                                                  modL4Port,
1327                                                                  ADDRESS_PORT_STRING);
1328
1329                         *diffModSipLen += diffLen;
1330
1331                         /* check for Call-Id. */
1332                         if (natSipAlgMsgFieldPos
1333                                         (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
1334                                 pSipMsg += pos;
1335                                 /* Call id 'addr" need to modified. */
1336                                 pTmpSipMsg = pSipMsg;
1337                                 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1338                                                                          SIP_ALG_CRLF, &pos,
1339                                                                          0);
1340                                 pTmpSipMsg += pos;
1341                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1342                                                                  0);
1343                                 pSipMsg += pos + 1;
1344                                 addrPortLen = pTmpSipMsg - pSipMsg;
1345                                 /* modify call id "addr" */
1346                                 pSipMsg =
1347                                                 natSipAlgModifyPayloadAddrPort(pSipMsg,
1348                                                                          &pSipMsgEnd,
1349                                                                          addrPortLen,
1350                                                                          &diffLen,
1351                                                                          modIp, 0,
1352                                                                  ADDRESS_PORT_STRING);
1353
1354                                 *diffModSipLen += diffLen;
1355 /* increase the overall diff between old & mod sip msg */
1356                         } else {
1357                                 printf("sip_alg_process; "
1358                                         "no valid Call-id field\n");
1359                                 return NULL;
1360                         }
1361 /* increase the overall diff between old & mod sip msg */
1362                 }
1363         } else if (call_direction == SIP_CALL_INCOMING) {
1364                 if ((msgType == SIP_ALG_INVITE_MSGTYPE)
1365                                 || (msgType == SIP_ALG_ACK_MSGTYPE)) {
1366                         /* need to modify Invite RL, TO field */
1367                         /* move to Invite RL IP address string */
1368                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0)
1369                                         == TRUE) {
1370                                 pSipMsg += pos + 1;
1371                                 pTmpSipMsg = pSipMsg;
1372                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_SIP,
1373                                                                  &pos, 0);
1374                                 pTmpSipMsg += (pos - 1);
1375 /* pointing to space before SIP/2.0 */
1376                                 addrPortLen = pTmpSipMsg - pSipMsg;
1377                         } else {
1378                                 printf
1379                                                 ("sip_alg_process: %d Invalid Invite RL\n",
1380                                                  __LINE__);
1381                                 return NULL;
1382                         }
1383                         /* modify Invite RL URI in payload */
1384                         pSipMsg =
1385                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1386                                                                  addrPortLen,
1387                                                                  &diffLen, modIp,
1388                                                                  modL4Port,
1389                                                                  ADDRESS_PORT_STRING);
1390                         *diffModSipLen += diffLen;
1391 /* increase the overall diff between old & mod sip msg */
1392
1393                         /* Advance to 'To" field */
1394                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1395                                         == TRUE) {
1396                                 pSipMsg += pos;
1397                                 pTmpSipMsg = pSipMsg;
1398                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1399                                                                  &pos, 0);
1400                                 pTmpSipMsg += pos;
1401                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1402                                                                  0);
1403                                 pSipMsg += pos + 1;
1404                                 addrPortLen = pTmpSipMsg - pSipMsg;
1405                         } else {
1406                                 printf("sip_alg_processing; "
1407                                         "%d Invalid To field\n",
1408                                                  __LINE__);
1409                                 return NULL;
1410                         }
1411                         /* Modify TO field IP addr:port in payload */
1412                         pSipMsg =
1413                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1414                                                                  addrPortLen,
1415                                                                  &diffLen, modIp,
1416                                                                  modL4Port,
1417                                                                  ADDRESS_PORT_STRING);
1418                         *diffModSipLen += diffLen;
1419 /* increase the overall diff between old & mod sip msg */
1420                 } else if ((msgType == SIP_ALG_TRYING_RINGING_MSGTYPE)
1421                                  || (msgType == SIP_ALG_200_OK_INVITE_MSGTYPE)) {
1422                         /* Need to modify TO field */
1423                         /* Advance to 'To" field */
1424                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1425                                         == TRUE) {
1426                                 pSipMsg += pos;
1427                                 pTmpSipMsg = pSipMsg;
1428                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1429                                                                  &pos, 0);
1430                                 pTmpSipMsg += pos;
1431                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1432                                                                  0);
1433                                 pSipMsg += pos + 1;
1434                                 addrPortLen = pTmpSipMsg - pSipMsg;
1435                                 pSipMsg =
1436                                                 natSipAlgModifyPayloadAddrPort(pSipMsg,
1437                                                                  &pSipMsgEnd,
1438                                                                  addrPortLen,
1439                                                                  &diffLen,
1440                                                                  modIp,
1441                                                                  modL4Port,
1442                                                          ADDRESS_PORT_STRING);
1443                                 *diffModSipLen += diffLen;
1444 /* increase the overall diff between old & mod sip msg */
1445                         }
1446                         if (msgType == SIP_ALG_200_OK_INVITE_MSGTYPE) {
1447 /* need to modify Contact, Remote-Party Id, SDP O=IN, C=IN, Audio Port */
1448                                 /* Advance to "Contact" field */
1449
1450                                 if (natSipAlgMsgFieldPos
1451                                                 (pSipMsg, SIP_ALG_CONTACT, &pos,
1452                                                  0) == TRUE) {
1453                                         pSipMsg += pos;
1454                                         /* move tmpMsg to CRLF */
1455                                         pTmpSipMsg = pSipMsg;
1456                                         natSipAlgMsgFieldPos(pTmpSipMsg,
1457                                                                          SIP_ALG_SEMICOLON,
1458                                                                          &pos, 0);
1459                                         pTmpSipMsg += pos;
1460                                         /* move sipMsg to addr:port string */
1461                                         int flag = 0;
1462                                         if (natSipAlgMsgFieldPos(pSipMsg,
1463                                                                          SIP_ALG_AT, &pos,
1464                                                                          30) == FALSE)
1465                                                 flag = 1;
1466
1467                                         if (flag)
1468                                                 goto SipMsgAdvance;
1469
1470                                         pSipMsg += pos + 1;
1471                                         addrPortLen = pTmpSipMsg - pSipMsg;
1472                                 } else {
1473                                         printf("sip_alg_process; "
1474                                         "No valid Call Id field\n");
1475                                         return NULL;
1476                                 }
1477                         /* Modify "Contact" field "addr:port" in payload */
1478                                 pSipMsg =
1479                                                 natSipAlgModifyPayloadAddrPort(pSipMsg,
1480                                                                  &pSipMsgEnd,
1481                                                                  addrPortLen,
1482                                                                  &diffLen,
1483                                                                  modIp,
1484                                                                  modL4Port,
1485                                                                  ADDRESS_PORT_STRING);
1486
1487                                 *diffModSipLen += diffLen;
1488 SipMsgAdvance:
1489                                 /* advance to Remote-Party Id */
1490                                 pTmpSipMsg = pSipMsg;
1491                                 if (natSipAlgMsgFieldPos
1492                                                 (pSipMsg, SIP_ALG_REMOTE_PARTY_ID, &pos,
1493                                                  0) == TRUE) {
1494                                         pSipMsg += pos +
1495                                                         strlen(SIP_ALG_REMOTE_PARTY_ID);
1496                                         pTmpSipMsg = pSipMsg;
1497                                         natSipAlgMsgFieldPos(pTmpSipMsg,
1498                                                                          SIP_ALG_GREAT,
1499                                                                          &pos, 0);
1500                                         pTmpSipMsg += pos;
1501                                         natSipAlgMsgFieldPos(pSipMsg,
1502                                                                          SIP_ALG_AT, &pos,
1503                                                                          0);
1504                                         pSipMsg += pos + 1;
1505                                         addrPortLen = pTmpSipMsg - pSipMsg;
1506                                         /* modify the field */
1507                                         pSipMsg =
1508                                                         natSipAlgModifyPayloadAddrPort
1509                                                         (pSipMsg, &pSipMsgEnd, addrPortLen,
1510                                                          &diffLen, modIp, modL4Port,
1511                                                          ADDRESS_PORT_STRING);
1512                                         diffModSipLen += diffLen;
1513                                 } else {
1514                                         printf("sip_alg_process: "
1515                                         "Remote-party-id is not in the msg\n");
1516                                         pSipMsg = pTmpSipMsg;
1517                                 }
1518
1519                                 /* Advance to SDP data message Owner address */
1520                                 if (natSipAlgMsgFieldPos
1521                                                 (pSipMsg, SIP_ALG_OWNER, &pos,
1522                                                  0) == TRUE) {
1523                                         pSipMsg += pos;
1524                                 /* at start of owner string "o=" */
1525                                         pTmpSipMsg = pSipMsg;
1526                                         /* move tmmsg to CRLF of owner field */
1527                                         natSipAlgMsgFieldPosFindCrlf(pSipMsg,
1528                                                                          SIP_ALG_CRLF,
1529                                                                          &pos,
1530                                                                          0);
1531                                         pTmpSipMsg += pos;
1532                                         /* start of CRLF "/r/n" */
1533 /* move pSipMsg to IP address string in owner field */
1534                                         natSipAlgMsgFieldPos(pSipMsg,
1535                                                                          SIP_ALG_IPV4, &pos,
1536                                                                          0);
1537                                         pSipMsg += (pos + strlen(SIP_ALG_IPV4));
1538                                         SKIP_SPACES(pSipMsg);
1539 /* after skipping spaces, pSip at start of addr */
1540                                         addrPortLen = pTmpSipMsg - pSipMsg;
1541                                 } else {
1542                                         printf("sip_alg_processing: "
1543                                                 "Invalid Owner field\n");
1544                                         return NULL;
1545                                 }
1546 /* Modify "Owner" field "addr" in payload.  Input L4 port as 0 */
1547                                 pSipMsg =
1548                                                 natSipAlgModifyPayloadAddrPort(pSipMsg,
1549                                                          &pSipMsgEnd,
1550                                                          addrPortLen,
1551                                                          &diffLen,
1552                                                          modIp, 0,
1553                                                          ADDRESS_PORT_STRING);
1554
1555                                 *diffModSipLen += diffLen;
1556                                 sdpMsgLen += diffLen;
1557                 /* update the sdpMsgLen after modification */
1558
1559                 /* Advance to Connection information to modify IP address */
1560                                 if (natSipAlgMsgFieldPos
1561                                                 (pSipMsg, SIP_ALG_CONN, &pos,
1562                                                  0) == TRUE) {
1563                                         pSipMsg += pos;
1564                                         pTmpSipMsg = pSipMsg;
1565                                         /* move tmmsg to CRLF of owner field */
1566                                         natSipAlgMsgFieldPosFindCrlf(pSipMsg,
1567                                                                         SIP_ALG_CRLF,
1568                                                                         &pos,
1569                                                                          0);
1570                                         pTmpSipMsg += pos;
1571                         /* start of CRLF "/r/n" */
1572                         /* move pSipMsg to IP address string in owner field */
1573                                         natSipAlgMsgFieldPos(pSipMsg,
1574                                                                          SIP_ALG_IPV4, &pos,
1575                                                                          0);
1576                                         pSipMsg += (pos + strlen(SIP_ALG_IPV4));
1577                                         SKIP_SPACES(pSipMsg);
1578 /* after skipping spaces, pSip at start of addr */
1579                                         addrPortLen = pTmpSipMsg - pSipMsg;
1580                                 } else {
1581                                         printf("sip_alg_processing: "
1582                                                 "Invalid Connection field\n");
1583                                         return NULL;
1584                                 }
1585 /* Modify "Connection" field "addr" in payload.  Input L4 port as 0 */
1586                                 pSipMsg =
1587                                                 natSipAlgModifyPayloadAddrPort(pSipMsg,
1588                                                                          &pSipMsgEnd,
1589                                                                          addrPortLen,
1590                                                                          &diffLen,
1591                                                                          modIp, 0,
1592                                                                  ADDRESS_PORT_STRING);
1593
1594                                 *diffModSipLen += diffLen;
1595                                 sdpMsgLen += diffLen;
1596 /* update the sdpMsgLen after modification */
1597
1598                                 /* Advance to RTP audio port */
1599                                 if (natSipAlgMsgFieldPos
1600                                                 (pSipMsg, SIP_ALG_AUDIO, &pos,
1601                                                  0) == TRUE) {
1602                                         pSipMsg +=
1603                                                         (pos + strlen(SIP_ALG_AUDIO));
1604                                         SKIP_SPACES(pSipMsg);
1605                                         pTmpSipMsg = pSipMsg;
1606                                         natSipAlgMsgFieldPosFindSpace
1607                                                         (pTmpSipMsg, SIP_ALG_SPACE, &pos,
1608                                                          0);
1609                                         pTmpSipMsg += pos;
1610                                         addrPortLen = pTmpSipMsg - pSipMsg;
1611                                 }
1612
1613 /* Modify "RTP Audio" port in payload. pass pub_ip as 0. */
1614                                 pSipMsg =
1615                                                 natSipAlgModifyPayloadAddrPort(pSipMsg,
1616                                                                          &pSipMsgEnd,
1617                                                                          addrPortLen,
1618                                                                          &diffLen, 0,
1619                                                                          modRtpPort,
1620                                                                          PORT_STRING);
1621
1622                                 *diffModSipLen += diffLen;
1623                                 sdpMsgLen += diffLen;
1624 /* update the sdpMsgLen after modification */
1625                         }
1626                 } else if (pkt_direction == PUBLIC
1627                                  && msgType == SIP_ALG_BYE_MSGTYPE) {
1628                         /* Modify Bye URL (if its BYE), To field */
1629
1630                         /* need to modify address:Port in Bye message string. */
1631                         natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0);
1632                         pSipMsg += pos + 1;
1633                         pTmpSipMsg = pSipMsg;
1634                         natSipAlgMsgFieldPosFindSpace(pTmpSipMsg, SIP_ALG_SPACE,
1635                                                                         &pos, 0);
1636                         pTmpSipMsg += pos;
1637                         addrPortLen = pTmpSipMsg - pSipMsg;
1638                         /* modify the "addr:port" in Bye message line */
1639                         pSipMsg =
1640                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1641                                                                  addrPortLen,
1642                                                                  &diffLen, modIp,
1643                                                                  modL4Port,
1644                                                                  ADDRESS_PORT_STRING);
1645                         *diffModSipLen += diffLen;
1646 /* increase the overall diff between old & mod sip msg */
1647
1648                         /* Advance to 'To" field */
1649                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1650                                         == TRUE) {
1651                                 pSipMsg += pos;
1652                                 pTmpSipMsg = pSipMsg;
1653                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1654                                                                  &pos, 0);
1655                                 pTmpSipMsg += pos;
1656                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1657                                                                  0);
1658                                 pSipMsg += pos + 1;
1659                                 addrPortLen = pTmpSipMsg - pSipMsg;
1660                                 pSipMsg =
1661                                                 natSipAlgModifyPayloadAddrPort(pSipMsg,
1662                                                                  &pSipMsgEnd,
1663                                                                  addrPortLen,
1664                                                                  &diffLen,
1665                                                                  modIp,
1666                                                                  modL4Port,
1667                                                                  ADDRESS_PORT_STRING);
1668                                 *diffModSipLen += diffLen;
1669 /* increase the overall diff between old & mod sip msg */
1670                         } else {
1671                                 printf
1672                                                 ("sip_alg_processing: Invalid TO field\n");
1673                                 return NULL;
1674                         }
1675                 } else if (pkt_direction == PRIVATE
1676                                  && msgType == SIP_ALG_BYE_MSGTYPE) {
1677                         /* change via and from field */
1678
1679                         /* Get to Via field IP address to modify */
1680                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
1681                                         == TRUE) {
1682                                 /* advance to IP/Port string */
1683                                 pSipMsg +=
1684                                                 (pos + strlen(SIP_ALG_VIA) +
1685                                                  SIP_ALG_VIA_FIELD_IPADDR);
1686                                 pTmpSipMsg = pSipMsg;
1687                                 /* move pTmp to next field */
1688                                 natSipAlgMsgFieldPos(pTmpSipMsg,
1689                                                                  SIP_ALG_SEMICOLON, &pos,
1690                                                                  0);
1691                                 pTmpSipMsg += pos;
1692                                 addrPortLen = pTmpSipMsg - pSipMsg;
1693                         } else {
1694                                 printf("sip_alg_process; No valid VIA field\n");
1695                                 return NULL;
1696                         }
1697                         /* Modify VIA field IP addr in payload */
1698                         pSipMsg =
1699                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1700                                                                  addrPortLen,
1701                                                                  &diffLen, modIp, 0,
1702                                                                  ADDRESS_PORT_STRING);
1703                         *diffModSipLen = diffLen;
1704
1705                         /* Advance to "From" field IP addr in payload */
1706                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
1707                                         == TRUE) {
1708                                 pSipMsg += pos; /* Moving to "From" */
1709                                 /* advance to IP/Port string */
1710                                 pTmpSipMsg = pSipMsg;
1711 /* move pTmpSipMsg to str ">" which is end of add:port string */
1712                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1713                                                                  &pos, 0);
1714                                 pTmpSipMsg += pos;
1715                                 diffLen = pTmpSipMsg - pSipMsg;
1716 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1717                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1718                                                                  0);
1719                                 pSipMsg += pos + 1;
1720 /* now its pointing to start of From field "address:port" */
1721                                 addrPortLen = pTmpSipMsg - pSipMsg;
1722                         } else {
1723                                 printf
1724                                                 ("sip_alg_process; No valid From field\n");
1725                                 return NULL;
1726                         }
1727                         /* Modify "From" field "addr:port" in payload */
1728                         pSipMsg =
1729                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1730                                                                  addrPortLen,
1731                                                                  &diffLen, modIp,
1732                                                                  modL4Port,
1733                                                                  ADDRESS_PORT_STRING);
1734
1735                         *diffModSipLen += diffLen;
1736 /* increase the overall diff between old & mod sip msg */
1737                 } else if (pkt_direction == PRIVATE
1738                                  && msgType == SIP_ALG_200_OK_BYE_MSGTYPE) {
1739                         /* change via and from field */
1740
1741                         /* Get to Via field IP address to modify */
1742                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
1743                                         == TRUE) {
1744                                 /* advance to IP/Port string */
1745                                 pSipMsg +=
1746                                                 (pos + strlen(SIP_ALG_VIA) +
1747                                                  SIP_ALG_VIA_FIELD_IPADDR);
1748                                 pTmpSipMsg = pSipMsg;
1749                                 /* move pTmp to next field */
1750                                 natSipAlgMsgFieldPos(pTmpSipMsg,
1751                                                                  SIP_ALG_SEMICOLON, &pos,
1752                                                                  0);
1753                                 pTmpSipMsg += pos;
1754                                 addrPortLen = pTmpSipMsg - pSipMsg;
1755                         } else {
1756                                 printf("sip_alg_process; No valid VIA field\n");
1757                                 return NULL;
1758                         }
1759                         /* Modify VIA field IP addr in payload */
1760                         pSipMsg =
1761                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1762                                                                  addrPortLen,
1763                                                                  &diffLen, modIp, 0,
1764                                                                  ADDRESS_PORT_STRING);
1765                         *diffModSipLen = diffLen;
1766
1767                         /* Advance to "From" field IP addr in payload */
1768                         if (natSipAlgMsgFieldPos(pSipMsg,
1769                                 SIP_ALG_FROM, &pos, 0) == TRUE) {
1770                                 pSipMsg += pos; /* Moving to "From" */
1771                                 /* advance to IP/Port string */
1772                                 pTmpSipMsg = pSipMsg;
1773 /* move pTmpSipMsg to str ">" which is end of add:port string */
1774                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1775                                                                  &pos, 0);
1776                                 pTmpSipMsg += pos;
1777                                 diffLen = pTmpSipMsg - pSipMsg;
1778 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1779                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1780                                                                  0);
1781                                 pSipMsg += pos + 1;
1782 /* now its pointing to start of From field "address:port" */
1783                                 addrPortLen = pTmpSipMsg - pSipMsg;
1784                         } else {
1785                                 printf
1786                                                 ("sip_alg_process; No valid From field\n");
1787                                 return NULL;
1788                         }
1789                         /* Modify "From" field "addr:port" in payload */
1790                         pSipMsg =
1791                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1792                                                                  addrPortLen,
1793                                                                  &diffLen, modIp,
1794                                                                  modL4Port,
1795                                                                  ADDRESS_PORT_STRING);
1796
1797                         *diffModSipLen += diffLen;
1798 /* increase the overall diff between old & mod sip msg */
1799                 } else if (pkt_direction == PUBLIC
1800                                  && msgType == SIP_ALG_200_OK_BYE_MSGTYPE) {
1801                         /* Get to To field IP address to modify */
1802                         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1803                                         == TRUE) {
1804                                 pSipMsg += pos; /* Moving to "From" */
1805                                 /* advance to IP/Port string */
1806                                 pTmpSipMsg = pSipMsg;
1807 /* move pTmpSipMsg to str ">" which is end of add:port string */
1808                                 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1809                                                                  &pos, 0);
1810                                 pTmpSipMsg += pos;
1811                                 diffLen = pTmpSipMsg - pSipMsg;
1812 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1813                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1814                                                                  0);
1815                                 pSipMsg += pos + 1;
1816 /* now its pointing to start of From field "address:port" */
1817                                 addrPortLen = pTmpSipMsg - pSipMsg;
1818                         } else {
1819                                 printf
1820                                                 ("sip_alg_process; no valid from field\n");
1821                                 return NULL;
1822                         }
1823                         /* Modify "From" field "addr:port" in payload */
1824                         pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg,
1825                                                          &pSipMsgEnd,
1826                                                          addrPortLen,
1827                                                          &diffLen, modIp,
1828                                                          modL4Port,
1829                                                          ADDRESS_PORT_STRING);
1830
1831                         *diffModSipLen = diffLen;
1832 /* increase the overall diff between old & mod sip msg */
1833
1834                         /* Advance to "Contact" field */
1835                         if (natSipAlgMsgFieldPos
1836                                         (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) {
1837                                 pSipMsg += pos;
1838                                 /* move tmpMsg to CRLF */
1839                                 pTmpSipMsg = pSipMsg;
1840                                 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1841                                                                  SIP_ALG_CRLF, &pos,
1842                                                                          0);
1843                                 pTmpSipMsg += pos;
1844                                 /* move sipMsg to addr:port string */
1845                                 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1846                                                                  0);
1847                                 pSipMsg += pos + 1;
1848                                 addrPortLen = pTmpSipMsg - pSipMsg;
1849                         } else {
1850                                 printf("sip_alg_process; "
1851                                         "No valid Call Id field\n");
1852                                 return NULL;
1853                         }
1854                         /* Modify "Contact" field "addr:port" in payload */
1855                         pSipMsg =
1856                                         natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1857                                                                  addrPortLen,
1858                                                                  &diffLen, modIp,
1859                                                                  modL4Port,
1860                                                                  ADDRESS_PORT_STRING);
1861
1862                         *diffModSipLen += diffLen;
1863                 }
1864         }
1865
1866 SipMsgAdvance2:
1867 /* need to remove the SIP ALG entry if msg is 200 OK BYE response */
1868         if (call_direction == SIP_CALL_OUTGOING) {
1869                 /* call remove sip alg entry here */
1870                 if (pkt_direction == PRIVATE) {
1871                         if (msgType == SIP_ALG_200_OK_BYE_MSGTYPE) {
1872                                 if (remove_sip_alg_entry
1873                                                 (rte_bswap32(ip_h->src_addr),
1874                                                  rte_bswap16(udp_h->src_port)) < 0)
1875                                         printf("removesipalgentry failed: "
1876                                                 "ipaddr %d, portid %d\n",
1877                                                          ip_h->src_addr, udp_h->src_port);
1878                         }
1879                 }
1880         } else {
1881                 if (pkt_direction == PUBLIC) {
1882                         if (msgType == SIP_ALG_200_OK_BYE_MSGTYPE) {
1883                                 if (remove_sip_alg_entry(pubIp, pubL4Port) < 0)
1884                                         printf("removesipalgentry failed: "
1885                                                 " ipaddr %d, portid %d\n",
1886                                                          pubIp, pubL4Port);
1887                         }
1888                 }
1889         }
1890
1891 /* adjust SDP msg len (sdpMsgLen) in the content length field of SIP msg */
1892         if ((sdpMsgLen > 0) && (sdpDataLen > 0)) {
1893                 pSipMsg = pStartSipMsg;
1894                 char *tmpSdpLen = NULL;
1895
1896                 sdpMsgLen += sdpDataLen;
1897                 tmpSdpLen = itoa(sdpMsgLen);
1898                 int tmpStrLen;
1899                 if (tmpSdpLen)
1900                         tmpStrLen = strlen(tmpSdpLen);
1901                 else
1902                         tmpStrLen = 0;
1903
1904         /* move to Content length field & change the length to sipMsgLen */
1905                 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0)
1906                                 == TRUE) {
1907                         pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN));
1908                         SKIP_SPACES(pSipMsg);
1909                         pTmpSipMsg = pSipMsg;
1910                         natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1911                                                                  SIP_ALG_DOUBLE_CRLF, &pos,
1912                                                                  0);
1913                         pTmpSipMsg += pos;
1914                         SKIP_SPACES(pSipMsg);
1915                         diffLen = pTmpSipMsg - pSipMsg;
1916                         natSipAlgAdjustMsg(pSipMsg, &pSipMsgEnd, tmpStrLen,
1917                                                  diffLen);
1918                         strncpy(pSipMsg, tmpSdpLen, tmpStrLen);
1919                 } else {
1920                         printf("sip_alg_process: Invalid Content Length\n");
1921                         return NULL;
1922                 }
1923         }
1924
1925  sipAlgProcessExit:
1926         /* need to return toe start of the SIP msg */
1927         return pStartSipMsg;
1928 }
1929
1930 /*
1931  * Function to Fetch RTP & RTCP port & return. Invoked by CGNAT
1932  * while adding NAPT entry for RTP & RTCP
1933  */
1934 int natSipAlgGetAudioPorts(struct rte_mbuf *pkt, uint16_t *rtpPort,
1935                                  uint16_t *rtcpPort)
1936 {
1937         struct ipv4_hdr *ip_h;
1938         struct ether_hdr *eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
1939         struct udp_hdr *udp_h;
1940         char *pSipMsg, *pEndPtr;
1941         int pos, sdpMsgLen;
1942
1943         ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1944         udp_h = (struct udp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1945         pSipMsg = ((char *)udp_h + sizeof(struct udp_hdr));
1946
1947         /* Advance to check content type & get content length (SDP length) */
1948         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTYPE, &pos, 0) == FALSE)
1949                 return -1;
1950
1951         pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTYPE));
1952         SKIP_SPACES(pSipMsg);
1953
1954         /*check the application/sdp type, if not, exit */
1955         if (!IS_STRING_SAME(pSipMsg, SIP_ALG_APPSDP)) {
1956                 printf("sip_alg_getAudioPort Invalid Content type\n");
1957                 return -1;
1958         }
1959
1960         /* get the SDP content length */
1961         natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0);
1962         pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN));
1963         SKIP_SPACES(pSipMsg);
1964         sdpMsgLen = strtol(pSipMsg, &pEndPtr, 10);
1965         if (!sdpMsgLen) {
1966                 printf("sipAlggetAudioport - sdpMsgLen is 0\n");
1967                 return -1;
1968         }
1969
1970         /* advance to RTP audio port */
1971         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AUDIO, &pos, 0) ==
1972                         TRUE) {
1973                 pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_AUDIO));
1974                 SKIP_SPACES(pSipMsg);
1975                 *rtpPort = strtol(pSipMsg, &pEndPtr, 10);
1976         } else
1977                 *rtpPort = 0;
1978
1979         /* advance to RTCP audio control port */
1980         if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_RTCP, &pos, 0) ==
1981                         TRUE) {
1982                 pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_RTCP));
1983                 SKIP_SPACES(pSipMsg);
1984                 *rtcpPort = strtol(pSipMsg, &pEndPtr, 10);
1985         } else
1986                 *rtcpPort = 0;
1987
1988         if (ALG_DEBUG)
1989                 printf(" sipAlgGetAudioPort; rtpPort %d, rtcpPort %d\n",
1990                                          *rtpPort, *rtcpPort);
1991         return 0;
1992 }
1993
1994 /* function to find SPACES in ALG message */
1995 int
1996 natSipAlgMsgFieldPosFindSpace(char *pData, const char *pIdStr, int *pPos,
1997                                                 int searchLen)
1998 {
1999         char *pStart = pData;
2000         int i = 0;
2001
2002         if (!pIdStr)
2003                 return FALSE;
2004
2005         if (!searchLen)
2006                 searchLen = 1500;       /* max default search length */
2007
2008         while (TRUE) {
2009                 while (*pData != ' ') {
2010                         pData++;
2011                         i++;
2012                 }
2013
2014                 if (i > searchLen) {
2015                         printf("SIP ALG Find Field Pos: "
2016                                 "Single message exceeds max len: %d\n",
2017                                 searchLen);
2018                         *pPos = searchLen;      /* reaches the end */
2019                         return FALSE;
2020                 }
2021
2022                 if (bcmp(pData, pIdStr, strlen(pIdStr)) == 0)
2023                         break;
2024         }
2025
2026         *pPos = pData - pStart;
2027         return TRUE;
2028 }
2029
2030 /* function to find CRLF in ALG message */
2031 int natSipAlgMsgFieldPosFindCrlf(
2032         char *pData,
2033         const char *pIdStr,
2034         int *pPos,
2035         int searchLen)
2036 {
2037         char *pStart = pData;
2038         int i = 0;
2039
2040         if (!pIdStr)
2041                 return FALSE;
2042
2043         if (!searchLen)
2044                 searchLen = 1500;       /* max default search length */
2045
2046         while (TRUE) {
2047                 while (*pData != '\r' && *(pData + 1) != '\n') {
2048                         pData++;
2049                         i++;
2050                 }
2051                 if (i >= searchLen) {
2052                         printf("SIP ALG Find Field Pos: "
2053                                 " Single message exceeds max len: %d\n",
2054                                          searchLen);
2055                         *pPos = searchLen;      /* reaches the end */
2056                         return FALSE;
2057                 }
2058
2059                 if (bcmp(pData, pIdStr, strlen(pIdStr)) == 0)
2060                         break;
2061         }
2062
2063         *pPos = pData - pStart;
2064         return TRUE;
2065 }
2066
2067 /* function to find field position in ALG message */
2068 int natSipAlgMsgFieldPos(char *pData,
2069         const char *pIdStr,
2070         int *pPos,
2071         int searchLen)
2072 {
2073         char *pStart = pData;
2074         int i = 0, j = 0;
2075
2076         if (!pIdStr)
2077                 return FALSE;
2078
2079         if (!searchLen)
2080                 searchLen = 1500;       /* max default search length */
2081
2082         while (TRUE) {
2083                 while (*pData != '\r' && *(pData + 1) != '\n') {
2084                         /* skip all space */
2085
2086                         while (*pData == ' ') {
2087                                 pData++;
2088                                 j++;
2089                         }
2090
2091                         if (*pData == '\r' && *(pData + 1) == '\n')
2092                                 break;
2093
2094                         if (bcmp(pData, pIdStr, strlen(pIdStr)) == 0) {
2095                                 *pPos = pData - pStart;
2096                                 return TRUE;
2097                         }
2098
2099                         pData++;
2100                         j++;
2101
2102                         if (j >= searchLen) {
2103                                 *pPos = pData - pStart;
2104                                 return FALSE;
2105                         }
2106
2107                 }
2108
2109                 /* advance to next line */
2110
2111                 for (i = 0; i < (searchLen - 1); i++) {
2112                         if (pData[i] == '\r')
2113                                 if (pData[i + 1] == '\n')
2114                                         break;
2115                 }
2116
2117                 if (i > searchLen) {
2118                         printf("SIP ALG Find Field Pos: "
2119                                 "Single message exceeds max len: %d\n",
2120                                          searchLen);
2121                         *pPos = searchLen;      /* reaches the end */
2122                         return FALSE;
2123                 }
2124
2125                 pData += i + 2;
2126                 searchLen -= (i + 2);
2127
2128                 if ((pData[0] == '\r' && pData[1] == '\n') ||
2129                                         (searchLen <= 0)) {
2130                         /* reach the end mark \r\n\r\n */
2131
2132                         if (searchLen > 0) {
2133                                 pData += 2;
2134                                 continue;
2135                         }
2136
2137                         *pPos = pData - pStart;
2138
2139                         return FALSE;
2140                 }
2141         }
2142
2143         *pPos = pData - pStart;
2144         return TRUE;
2145 }
2146
2147 /* get SIP Call id string */
2148 char *getSipCallIdStr(char *pMsg)
2149 {
2150         char *pStart;
2151         char *pCallId = NULL;
2152         int i;
2153
2154         pStart = pMsg;
2155         for (i = 0; i < 200; i++) {
2156                 if (*pMsg != '\r')
2157                         pMsg++;
2158                 else
2159                         break;
2160         }
2161         if (i >= 200) {
2162                 printf("SIP_ALG: getCallid wrong string format\n");
2163                 return NULL;
2164         }
2165
2166         size_t size = RTE_CACHE_LINE_ROUNDUP(pMsg - pStart + 1);
2167
2168         pCallId = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
2169         if (!pCallId)
2170                 return NULL;
2171
2172         bcopy(pStart, pCallId, pMsg - pStart);
2173         *(pCallId + (pMsg - pStart)) = 0;
2174
2175         if (ALG_DEBUG)
2176                 printf("%s: %s\n", __func__, pCallId);
2177
2178         return pCallId;
2179 }
2180
2181 char *natSipAlgModifyPayloadAddrPort(
2182         char *pSipMsg, char **pSipMsgEnd,
2183         uint32_t oldStrLen, uint32_t *diffLen,
2184         uint32_t modIp, uint16_t modPort, uint32_t type)
2185 {
2186         char addrport[MAX_ADDR_PORT_SIZE];
2187         struct in_addr ipAddr;
2188         uint32_t newStrLen = 0;
2189         char *tmpPort = NULL;
2190
2191         if (modPort != 0)
2192                 tmpPort = itoa(modPort);
2193
2194         *diffLen = 0;
2195         if (type == ADDRESS_PORT_STRING) {
2196                 ipAddr.s_addr = htonl(modIp);
2197                 char *tmpAddr = inet_ntoa(ipAddr);
2198
2199                 if (modPort != 0)       /* for addr:port combo modification */
2200                         sprintf(addrport, "%s:%s", tmpAddr, tmpPort);
2201                 else            /* if only address modification */
2202                         sprintf(addrport, "%s", tmpAddr);
2203
2204                 newStrLen = strlen(addrport);
2205
2206                 if (abs(newStrLen - oldStrLen) > 0) {
2207                 /*
2208                  * Call the function moving the SIP Msg pointer
2209                  * to modify the field
2210                  */
2211                         natSipAlgAdjustMsg(pSipMsg, pSipMsgEnd,
2212                                                         newStrLen, oldStrLen);
2213                 }
2214
2215                 /* replace the old addr:port with new addr:port */
2216                 strncpy(pSipMsg, addrport, strlen(addrport));
2217         } else if (type == PORT_STRING) {       /* only port modification */
2218                 if(tmpPort)
2219                 newStrLen = strlen(tmpPort);
2220
2221                 if (abs(newStrLen - oldStrLen) > 0) {
2222                 /*
2223                  * Call the function moving the SIP msg pointer
2224                  * to modify the field
2225                  */
2226                         natSipAlgAdjustMsg(pSipMsg, pSipMsgEnd,
2227                                                         newStrLen, oldStrLen);
2228                 }
2229
2230                 /* replace the old port with new port */
2231                 if(tmpPort)
2232                 strncpy(pSipMsg, tmpPort, strlen(tmpPort));
2233         }
2234         /* output difflen between old str len & modified new str length */
2235         if (newStrLen > oldStrLen)
2236                 *diffLen = newStrLen - oldStrLen;
2237
2238         if (tmpPort)
2239                 free(tmpPort);
2240
2241         return pSipMsg;         /* modified SIP Msg */
2242 }
2243
2244 char *natSipAlgAdjustMsg(char *pSipMsg, char **pSipMsgEnd,
2245                          uint32_t newStrLen, uint32_t oldStrLen)
2246 {
2247         char MsgBuffer[MAX_SIP_UDP_MSG_SIZE];
2248
2249         if (newStrLen > oldStrLen) {
2250                 pSipMsg += oldStrLen;
2251                 int msgLen = *pSipMsgEnd - pSipMsg;
2252
2253                 strncpy(MsgBuffer, pSipMsg, msgLen);
2254                 pSipMsg += (newStrLen - oldStrLen);
2255                 strncpy(pSipMsg, MsgBuffer, msgLen);
2256
2257                 if (ALG_DEBUG)
2258                         printf("natSipAlgAdjustMsg: %u\n", msgLen);
2259
2260                 /* moving output end of SIP MSG by difflen like pSipMsg */
2261                 *pSipMsgEnd += (newStrLen - oldStrLen);
2262         } else {
2263                 /* Setting space on the oldStr position */
2264                 memset(pSipMsg, ' ', oldStrLen);
2265         }
2266
2267         return pSipMsg;
2268 }
2269
2270 /* end of file */