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