2 // Copyright (c) 2017 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <arpa/inet.h>
26 #include <rte_common.h>
27 #include <rte_malloc.h>
30 #include <rte_byteorder.h>
31 #include <rte_table_lpm.h>
32 #include <rte_table_hash.h>
33 #include <rte_pipeline.h>
37 #include <rte_jhash.h>
38 #include <rte_cycles.h>
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"
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 ";"
77 #define SIP_DEFAULT_L4PORT 5060
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
86 #define MAX_NUM_SIP_ALG_ENTRIES 16384
88 #define SIP_ALG_VIA_FIELD_IPADDR 14
89 #define SIP_ALG_CTAC_FIELD_IPADDR 7
91 #define ADDRESS_PORT_STRING 1
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
101 enum { FALSE, TRUE };
103 struct rte_mempool *lib_alg_pktmbuf_tx_pool;
105 struct rte_mbuf *lib_alg_pkt;
107 static struct rte_hash_parameters sip_alg_hash_params = {
109 .entries = MAX_NUM_SIP_ALG_ENTRIES,
111 .key_len = sizeof(struct sip_alg_key),
112 .hash_func = rte_jhash,
113 .hash_func_init_val = 0,
117 struct rte_hash *sip_alg_hash_table;
119 struct sip_alg_table_entry *sip_alg_table[MAX_NUM_SIP_ALG_ENTRIES];
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,
132 char *natSipAlgAdjustMsg(char *pSipMsg, char **pSipMsgEnd,
133 uint32_t newStrLen, uint32_t oldStrLen);
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)
139 char *s = rte_zmalloc(NULL, 64, RTE_CACHE_LINE_SIZE);;
141 /* create ipv4 hash */
143 printf("NAT SIP ALG Init failed\n");
146 snprintf(s, strlen(s), "ipv4_sip_alg_hash_%d", socketid);
147 printf("NAT SIP ALG initialization ...\n");
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);
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");
159 printf("sip_alg_hash_table %p\n\n", (void *)sip_alg_hash_table);
167 int len = n == 0 ? 1 : floor(log10l(labs(n))) + 1;
170 len++; /* room for negative sign '-' */
172 char *buf = calloc(sizeof(char), len + 1); // +1 for null
174 snprintf(buf, len + 1, "%ld", n);
178 struct sip_alg_table_entry *retrieve_sip_alg_entry(
179 struct sip_alg_key *alg_key);
181 struct sip_alg_table_entry *retrieve_sip_alg_entry(
182 struct sip_alg_key *alg_key)
184 struct sip_alg_table_entry *sip_alg_data = NULL;
186 int ret = rte_hash_lookup(sip_alg_hash_table, alg_key);
190 printf("alg-hash lookup failed ret %d, "
191 "EINVAL %d, ENOENT %d\n",
192 ret, EINVAL, ENOENT);
195 sip_alg_data = sip_alg_table[ret];
202 //int remove_sip_alg_entry(uint32_t ipaddr, uint16_t portid);
203 int remove_sip_alg_entry(uint32_t ipaddr, uint16_t portid)
205 struct sip_alg_key alg_key;
206 void *sip_alg_entry_data;
209 alg_key.l4port = portid;
210 alg_key.ip_address = ipaddr;
215 printf("remove_sip_entry ip %x, port %d\n", alg_key.ip_address,
218 ret = rte_hash_lookup(sip_alg_hash_table, &alg_key);
221 printf("removesipalgentry: "
222 "rtehashlookup failed with error %d",
227 sip_alg_entry_data = sip_alg_table[ret];
229 free(sip_alg_entry_data);
230 rte_hash_del_key(sip_alg_hash_table, &alg_key);
236 * Function for populating SIP ALG entry. return 0 - success &
237 * return -1 - failure
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)
246 struct sip_alg_key alg_key;
248 alg_key.l4port = portid;
249 alg_key.ip_address = ipaddr;
255 printf("populate_sip_alg_entry port %d, ip %x\n",
256 alg_key.l4port, alg_key.ip_address);
258 struct sip_alg_table_entry *new_alg_data =
259 retrieve_sip_alg_entry(&alg_key);
263 printf("sip_alg_entry exists ip%x, port %d\n",
264 alg_key.ip_address, alg_key.l4port);
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");
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;
285 ret = rte_hash_add_key(sip_alg_hash_table, &alg_key);
287 printf("populate sip - rte_hash_add_key_data ERROR %d\n", ret);
292 sip_alg_table[ret] = new_alg_data;
295 printf("SIP_ALG: table update - ip=%x on port=%d ret=%d\n",
296 alg_key.ip_address, portid, ret);
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)
306 uint16_t msgType = 0;
307 enum sip_alg_call_direction call_direction = 0;
308 uint32_t ip_address = 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;
318 struct sip_alg_key alg_key;
319 uint16_t diffModSipLen = 0;
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));
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);
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) ==
341 getSipCallIdStr(pSipMsg + pos +
342 TAG_TO_DATAPOS(SIP_ALG_CALLID));
345 printf("sipalgdpi: %d call id %s\n", __LINE__,
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;
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);
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,
368 printf("sipalgdpi:populate SIP alg UDP entry failed\n");
371 if (modRtpPort != 0) {
372 ret = populate_sip_alg_entry(ip_address, modRtpPort,
374 call_direction, SIP_RTP);
377 "populate SIP alg entry RTP failed\n");
381 if (modRtcpPort != 0) {
382 ret = populate_sip_alg_entry(ip_address, modRtcpPort,
384 call_direction, SIP_RTCP);
387 "populate SIP alg entry RTCP failed\n");
392 /* Call ALG packet process function for checking & payload modification */
394 sip_alg_process(pkt, pkt_direction, call_direction,
395 SIP_ALG_INVITE_MSGTYPE, modIp, modL4Port, 0,
396 0, modRtpPort, modRtcpPort, &diffModSipLen);
399 * not SIP INVITE, could be SIP response 200 OK invite, 100 trying,
400 * 180 ringing or BYE or 200 OK BYe
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);
407 alg_key.ip_address = pubIp;
408 alg_key.l4port = pubL4Port;
413 sip_alg_entry = retrieve_sip_alg_entry(&alg_key);
416 printf("%s: sip_alg_entry_ptr(%p)\n", __func__,
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);
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;
431 } else if (IS_STRING_SAME(pSipMsg, SIP_ALG_ACK)) {
432 msgType = SIP_ALG_ACK_MSGTYPE;
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) {
447 TAG_TO_DATAPOS(SIP_ALG_CSEQ);
449 /* skip the number field */
453 if (IS_STRING_SAME(pBye, SIP_ALG_BYE)
456 (pBye, SIP_ALG_CANCEL)))
458 SIP_ALG_200_OK_BYE_MSGTYPE;
462 SIP_ALG_200_OK_INVITE_MSGTYPE;
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;
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,
477 /* Call SIP alg processing for further processing. */
479 sip_alg_process(pkt, pkt_direction, call_direction,
480 msgType, modIp, modL4Port, pubIp,
481 pubL4Port, modRtpPort, modRtcpPort,
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));
491 * need to modify mbuf & modified length of payload in the IP/UDP
492 * header length fields and return to CGNAT for transmitting
495 if (diffModSipLen > 0) {
496 len = rte_bswap16(udp_h->dgram_len);
497 len += diffModSipLen;
498 udp_h->dgram_len = rte_bswap16(len);
500 len = rte_bswap16(ip_h->total_length);
501 len += diffModSipLen;
502 ip_h->total_length = rte_bswap16(len);
504 if (rte_pktmbuf_append(pkt, diffModSipLen) == NULL)
505 printf("%s: pktmbuf_append returns NULL", __func__);
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),
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)
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;
533 /* diff between old & new modified field len */
534 uint32_t diffLen, addrPortLen;
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;
545 rte_bswap16(ip_h->total_length) - sizeof(struct ipv4_hdr) -
546 sizeof(struct udp_hdr);
548 if (natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0) ==
550 pTmpSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN));
552 printf("sip_alg_process: Invalid Content Length\n");
556 SKIP_SPACES(pTmpSipMsg);
557 int sdpDataLen = strtol(pTmpSipMsg, &pStr, 10);
559 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_DOUBLE_CRLF, &pos, 0);
560 pTmpSipMsg += (pos + strlen(SIP_ALG_DOUBLE_CRLF));
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,
570 pTmpSipMsg += (pos + strlen(SIP_ALG_DOUBLE_CRLF));
573 int sipMsgLen = (pTmpSipMsg - pSipMsg);
575 char *pSipMsgEnd = pSipMsg + sipMsgLen + sdpDataLen;
578 printf("%s: pSipMsg: %p, pSipMsgEnd: %p, sipMsgLen: %d, "
579 "sdpDataLen: %d totalSipMsgLen: %d\n",
580 __func__, pSipMsg, pSipMsgEnd, sipMsgLen, sdpDataLen,
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)
589 /* advance to IP/Port string */
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,
599 addrPortLen = pTmpSipMsg - pSipMsg;
601 printf("sip_alg_process; No valid VIA field\n");
604 /* Modify VIA field IP addr:port in payload */
606 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
610 ADDRESS_PORT_STRING);
612 *diffModSipLen += diffLen;
613 /* increase the overall diff between old & mod sip msg */
615 /* Advance to "From" field IP addr in payload */
616 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
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,
625 diffLen = pTmpSipMsg - pSipMsg;
626 /* find "@" from "From" string to ">" string which is start of "addr:port" */
627 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
630 /* now its pointing to start of From field "address:port" */
631 addrPortLen = pTmpSipMsg - pSipMsg;
634 ("sip_alg_process; No valid From field\n");
637 /* Modify "From" field "addr:port" in payload */
639 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
643 ADDRESS_PORT_STRING);
645 *diffModSipLen += diffLen;
646 /* increase the overall diff between old & mod sip msg */
648 /* Advance to Call id field */
649 if (natSipAlgMsgFieldPos
650 (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
652 /* moving it to start of string "Call-ID" */
653 pTmpSipMsg = pSipMsg;
654 /* move tmpSipMsg to next field */
655 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
659 diffLen = pTmpSipMsg - pSipMsg;
660 /* Move pSipMsg to start of Call id "IP addr" string */
661 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
664 addrPortLen = pTmpSipMsg - pSipMsg;
666 printf("sip_alg_process; "
667 " No valid Call Id field\n");
670 /* Modify "Call-id" field "addr:port" in payload */
671 /* L4 port input is made as 0 as its only addr string modification */
673 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
676 ADDRESS_PORT_STRING);
678 *diffModSipLen += diffLen;
680 /* Advance to "Contact" field */
681 if (natSipAlgMsgFieldPos
682 (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) {
684 /* move tmpMsg to CRLF */
685 pTmpSipMsg = pSipMsg;
686 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
690 /* move sipMsg to addr:port string */
691 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
694 addrPortLen = pTmpSipMsg - pSipMsg;
697 printf("sip_alg_process; "
698 "No valid Call Id field\n");
701 /* Modify "Contact" field "addr:port" in payload */
703 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
707 ADDRESS_PORT_STRING);
709 *diffModSipLen += diffLen;
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,
718 TAG_TO_DATAPOS(SIP_ALG_CONTYPE));
719 SKIP_SPACES(pSipMsg);
720 /*check the application/sdp type, if not, exit */
722 (pSipMsg, SIP_ALG_APPSDP)) {
723 printf("sip_alg_process "
724 "Invalid Content type\n");
728 printf("sip_alg_process; "
729 "No valid Content field\n");
733 /* get the SDP content length */
734 natSipAlgMsgFieldPos(pSipMsg,
735 SIP_ALG_CONTENT_LEN, &pos,
738 (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN));
739 SKIP_SPACES(pSipMsg);
740 sdpMsgLen = strtol(pSipMsg, &pEndPtr, 10);
742 /* if ACK message, SDP content wont be there.go to ALG process complete */
743 if (msgType == SIP_ALG_ACK_MSGTYPE)
744 goto sipAlgProcessExit;
746 printf("sip_alg_process - "
751 /* Advance to SDP data message Owner address */
752 if (natSipAlgMsgFieldPos
753 (pSipMsg, SIP_ALG_OWNER, &pos,
756 /* at start of owner string "o=" */
757 pTmpSipMsg = pSipMsg;
758 /* move tmmsg to CRLF of owner field */
759 natSipAlgMsgFieldPosFindCrlf(pSipMsg,
764 /* start of CRLF "/r/n" */
765 /* move pSipMsg to IP address string in owner field */
766 natSipAlgMsgFieldPos(pSipMsg,
769 pSipMsg += (pos + strlen(SIP_ALG_IPV4));
770 SKIP_SPACES(pSipMsg);
771 /* after skipping spaces, pSip at start of addr */
772 addrPortLen = pTmpSipMsg - pSipMsg;
774 printf("sip_alg_processing: "
775 "Invalid Owner field\n");
778 /* Modify "Owner" field "addr" in payload. Input L4 port as 0 */
780 natSipAlgModifyPayloadAddrPort(pSipMsg,
785 ADDRESS_PORT_STRING);
787 *diffModSipLen += diffLen;
788 sdpMsgLen += diffLen;
789 /* need to adjust the SDP msg len as modification done. */
791 /* Advance to Connection information to modify IP address */
792 if (natSipAlgMsgFieldPos
793 (pSipMsg, SIP_ALG_CONN, &pos,
796 pTmpSipMsg = pSipMsg;
797 /* move tmmsg to CRLF of owner field */
798 natSipAlgMsgFieldPosFindCrlf(pSipMsg,
803 /* start of CRLF "/r/n" */
804 /* move pSipMsg to IP address string in owner field */
805 natSipAlgMsgFieldPos(pSipMsg,
808 pSipMsg += (pos + strlen(SIP_ALG_IPV4));
809 SKIP_SPACES(pSipMsg);
810 /* after skipping spaces, pSip at start of addr */
811 addrPortLen = pTmpSipMsg - pSipMsg;
813 printf("sip_alg_processing: "
814 "Invalid Owner field\n");
817 /* Modify "Connection" field "addr" in payload. Input L4 port as 0 */
819 natSipAlgModifyPayloadAddrPort(pSipMsg,
824 ADDRESS_PORT_STRING);
826 *diffModSipLen += diffLen;
827 sdpMsgLen += diffLen;
828 /* need to adjust the SDP msg len as modification done. */
830 /* Advance to RTP audio port */
831 if (natSipAlgMsgFieldPos
832 (pSipMsg, SIP_ALG_AUDIO, &pos,
836 TAG_TO_DATAPOS(SIP_ALG_AUDIO));
837 SKIP_SPACES(pSipMsg);
838 pTmpSipMsg = pSipMsg;
839 natSipAlgMsgFieldPosFindSpace
840 (pTmpSipMsg, SIP_ALG_SPACE, &pos,
843 addrPortLen = pTmpSipMsg - pSipMsg;
846 /* Modify "RTP Audio" port in payload. pass pub_ip as 0. */
848 natSipAlgModifyPayloadAddrPort(pSipMsg,
855 *diffModSipLen += diffLen;
856 sdpMsgLen += diffLen;
857 /* need to adjust the SDP msg len as modification done. */
859 /* Advance to RTCP control port, if its there */
860 if (natSipAlgMsgFieldPos
861 (pSipMsg, SIP_ALG_RTCP, &pos,
865 TAG_TO_DATAPOS(SIP_ALG_RTCP));
866 SKIP_SPACES(pSipMsg);
867 pTmpSipMsg = pSipMsg;
868 natSipAlgMsgFieldPosFindSpace
869 (pTmpSipMsg, SIP_ALG_SPACE, &pos,
872 addrPortLen = pTmpSipMsg - pSipMsg;
874 /* Modify "RTP Audio" port in payload. pass pub_ip as 0. */
876 natSipAlgModifyPayloadAddrPort
877 (pSipMsg, &pSipMsgEnd, addrPortLen,
878 &diffLen, 0, modRtcpPort,
881 *diffModSipLen += diffLen;
882 sdpMsgLen += diffLen;
883 /* need to adjust the SDP msg len as modification done. */
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)
892 /* advance to IP/Port string */
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,
902 addrPortLen = pTmpSipMsg - pSipMsg;
904 printf("sip_alg_process; No valid VIA field\n");
907 /* Modify VIA field IP addr:port in payload */
909 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
913 ADDRESS_PORT_STRING);
914 *diffModSipLen = diffLen;
916 /* Advance to "From" field IP addr in payload */
917 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
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,
926 //diffLen = pTmpSipMsg - pSipMsg;
927 /* find "@" from "From" string to ">" string which is start of "addr:port" */
928 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
931 /* now its pointing to start of From field "address:port" */
932 addrPortLen = pTmpSipMsg - pSipMsg;
935 ("sip_alg_process; No valid From field\n");
938 /* Modify "From" field "addr:port" in payload */
940 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
944 ADDRESS_PORT_STRING);
946 *diffModSipLen += diffLen;
947 /* increase the overall diff between old & mod sip msg */
949 /* Advance to Call id field */
950 if (natSipAlgMsgFieldPos
951 (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
953 /* moving it to start of string "Call-ID" */
954 pTmpSipMsg = pSipMsg;
955 /* move tmpSipMsg to next field */
956 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
960 //diffLen = pTmpSipMsg - pSipMsg;
961 /* Move pSipMsg to start of Call id "IP addr" string */
962 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
965 addrPortLen = pTmpSipMsg - pSipMsg;
967 printf("sip_alg_process; "
968 "No valid Call Id field\n");
971 /* Modify "Call-id" field "addr" in payload */
972 /* L4 port input is made as 0 as its only addr string modification */
974 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
977 ADDRESS_PORT_STRING);
979 *diffModSipLen += diffLen;
981 } else if (pkt_direction == PRIVATE
982 && msgType == SIP_ALG_BYE_MSGTYPE) {
983 /* change via, from, call-id and contact field */
985 /* Get to Via field IP address to modify */
986 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
988 /* advance to IP/Port string */
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,
998 addrPortLen = pTmpSipMsg - pSipMsg;
1000 printf("sip_alg_process; No valid VIA field\n");
1003 /* Modify VIA field IP addr in payload */
1005 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1008 ADDRESS_PORT_STRING);
1009 *diffModSipLen = diffLen;
1011 /* Advance to "From" field IP addr in payload */
1012 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
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,
1021 diffLen = pTmpSipMsg - pSipMsg;
1022 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1023 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1026 /* now its pointing to start of From field "address:port" */
1027 addrPortLen = pTmpSipMsg - pSipMsg;
1030 ("sip_alg_process; No valid From field\n");
1033 /* Modify "From" field "addr:port" in payload */
1035 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1039 ADDRESS_PORT_STRING);
1041 *diffModSipLen += diffLen;
1042 /* increase the overall diff between old & mod sip msg */
1044 /* Advance to Call id field */
1045 if (natSipAlgMsgFieldPos
1046 (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
1048 /* moving it to start of string "Call-ID" */
1049 pTmpSipMsg = pSipMsg;
1050 /* move tmpSipMsg to next field */
1051 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1055 diffLen = pTmpSipMsg - pSipMsg;
1056 /* Move pSipMsg to start of Call id "IP addr" string */
1057 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1060 addrPortLen = pTmpSipMsg - pSipMsg;
1062 printf("sip_alg_process; "
1063 "No valid Call Id field\n");
1066 /* Modify "Call-id" field "addr:port" in payload */
1067 /* L4 port input is made as 0 as its only addr string modification */
1069 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1072 ADDRESS_PORT_STRING);
1074 *diffModSipLen += diffLen;
1076 /* Advance to "Contact" field */
1077 if (natSipAlgMsgFieldPos
1078 (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) {
1080 /* move tmpMsg to semicolon */
1081 pTmpSipMsg = pSipMsg;
1082 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1083 SIP_ALG_CRLF, &pos, 0);
1085 /* move sipMsg to addr:port string */
1087 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT,
1092 goto SipMsgAdvance2;
1094 addrPortLen = pTmpSipMsg - pSipMsg;
1097 printf("sip_alg_process; "
1098 "No valid Call Id field\n");
1101 /* Modify "Contact" field "addr:port" in payload */
1103 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1107 ADDRESS_PORT_STRING);
1109 *diffModSipLen += diffLen;
1110 } else if (pkt_direction == PUBLIC
1111 && msgType == SIP_ALG_BYE_MSGTYPE) {
1113 * Modify Bye URL (if its BYE), To field,
1114 * Call-Id if call triggered from private, then modify
1117 /* need to modify address:Port in Bye message string. */
1118 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0);
1120 pTmpSipMsg = pSipMsg;
1121 natSipAlgMsgFieldPosFindSpace(pTmpSipMsg, SIP_ALG_SPACE,
1124 addrPortLen = pTmpSipMsg - pSipMsg;
1125 /* modify the "addr:port" in Bye message line */
1127 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1131 ADDRESS_PORT_STRING);
1132 *diffModSipLen += diffLen;
1133 /* increase the overall diff between old & mod sip msg */
1135 /* Advance to 'To" field */
1136 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1139 pTmpSipMsg = pSipMsg;
1140 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1143 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1146 addrPortLen = pTmpSipMsg - pSipMsg;
1148 natSipAlgModifyPayloadAddrPort(pSipMsg,
1154 ADDRESS_PORT_STRING);
1155 *diffModSipLen += diffLen;
1156 /* increase the overall diff between old & mod sip msg */
1159 /* check for Call-Id. */
1160 if (natSipAlgMsgFieldPos
1161 (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
1163 /* moving it to start of string "Call-ID" */
1164 pTmpSipMsg = pSipMsg;
1165 /* move tmpSipMsg to next field */
1166 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1170 //diffLen = pTmpSipMsg - pSipMsg;
1171 /* Move pSipMsg to start of Call id "IP addr" string */
1172 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1175 addrPortLen = pTmpSipMsg - pSipMsg;
1177 printf("sip_alg_process; "
1178 "No valid Call Id field\n");
1181 /* Modify "Call-id" field "addr" in payload */
1182 /* L4 port input is made as 0 as its only addr string modification */
1184 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1187 ADDRESS_PORT_STRING);
1189 *diffModSipLen += diffLen;
1190 } else if (pkt_direction == PRIVATE
1191 && (msgType == SIP_ALG_200_OK_BYE_MSGTYPE)) {
1193 * Need to modify To field, Call-Id,
1194 * Contact if call triggered from private, then modify
1196 /* Get to To field IP address to modify */
1197 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
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,
1206 diffLen = pTmpSipMsg - pSipMsg;
1207 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1208 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1211 /* now its pointing to start of From field "address:port" */
1212 addrPortLen = pTmpSipMsg - pSipMsg;
1215 ("sip_alg_process; no valid from field\n");
1218 /* Modify "From" field "addr:port" in payload */
1220 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1224 ADDRESS_PORT_STRING);
1226 *diffModSipLen = diffLen;
1227 /* increase the overall diff between old & mod sip msg */
1229 /* Advance to "Contact" field */
1230 if (natSipAlgMsgFieldPos
1231 (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) {
1233 /* move tmpMsg to CRLF */
1234 pTmpSipMsg = pSipMsg;
1235 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1239 /* move sipMsg to addr:port string */
1241 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT,
1246 goto SipMsgAdvance2;
1248 addrPortLen = pTmpSipMsg - pSipMsg;
1250 printf("sip_alg_process; "
1251 "No valid Call Id field\n");
1254 /* Modify "Contact" field "addr:port" in payload */
1256 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1260 ADDRESS_PORT_STRING);
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 */
1267 /* Get to Via field IP address to modify */
1268 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
1270 /* advance to IP/Port string */
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,
1280 addrPortLen = pTmpSipMsg - pSipMsg;
1282 printf("sip_alg_process; No valid VIA field\n");
1285 /* Modify VIA field IP addr in payload */
1287 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1290 ADDRESS_PORT_STRING);
1291 *diffModSipLen = diffLen;
1293 /* Advance to "From" field IP addr in payload */
1294 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
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,
1303 diffLen = pTmpSipMsg - pSipMsg;
1304 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1305 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1308 /* now its pointing to start of From field "address:port" */
1309 addrPortLen = pTmpSipMsg - pSipMsg;
1312 ("sip_alg_process; No valid From field\n");
1315 /* Modify "From" field "addr:port" in payload */
1317 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1321 ADDRESS_PORT_STRING);
1323 *diffModSipLen += diffLen;
1325 /* check for Call-Id. */
1326 if (natSipAlgMsgFieldPos
1327 (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
1329 /* Call id 'addr" need to modified. */
1330 pTmpSipMsg = pSipMsg;
1331 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1335 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1338 addrPortLen = pTmpSipMsg - pSipMsg;
1339 /* modify call id "addr" */
1341 natSipAlgModifyPayloadAddrPort(pSipMsg,
1346 ADDRESS_PORT_STRING);
1348 *diffModSipLen += diffLen;
1349 /* increase the overall diff between old & mod sip msg */
1351 printf("sip_alg_process; "
1352 "no valid Call-id field\n");
1355 /* increase the overall diff between old & mod sip msg */
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)
1365 pTmpSipMsg = pSipMsg;
1366 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_SIP,
1368 pTmpSipMsg += (pos - 1);
1369 /* pointing to space before SIP/2.0 */
1370 addrPortLen = pTmpSipMsg - pSipMsg;
1373 ("sip_alg_process: %d Invalid Invite RL\n",
1377 /* modify Invite RL URI in payload */
1379 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1383 ADDRESS_PORT_STRING);
1384 *diffModSipLen += diffLen;
1385 /* increase the overall diff between old & mod sip msg */
1387 /* Advance to 'To" field */
1388 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1391 pTmpSipMsg = pSipMsg;
1392 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1395 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1398 addrPortLen = pTmpSipMsg - pSipMsg;
1400 printf("sip_alg_processing; "
1401 "%d Invalid To field\n",
1405 /* Modify TO field IP addr:port in payload */
1407 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
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)
1421 pTmpSipMsg = pSipMsg;
1422 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1425 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1428 addrPortLen = pTmpSipMsg - pSipMsg;
1430 natSipAlgModifyPayloadAddrPort(pSipMsg,
1436 ADDRESS_PORT_STRING);
1437 *diffModSipLen += diffLen;
1438 /* increase the overall diff between old & mod sip msg */
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 */
1444 if (natSipAlgMsgFieldPos
1445 (pSipMsg, SIP_ALG_CONTACT, &pos,
1448 /* move tmpMsg to CRLF */
1449 pTmpSipMsg = pSipMsg;
1450 natSipAlgMsgFieldPos(pTmpSipMsg,
1454 /* move sipMsg to addr:port string */
1456 if (natSipAlgMsgFieldPos(pSipMsg,
1465 addrPortLen = pTmpSipMsg - pSipMsg;
1467 printf("sip_alg_process; "
1468 "No valid Call Id field\n");
1471 /* Modify "Contact" field "addr:port" in payload */
1473 natSipAlgModifyPayloadAddrPort(pSipMsg,
1479 ADDRESS_PORT_STRING);
1481 *diffModSipLen += diffLen;
1483 /* advance to Remote-Party Id */
1484 pTmpSipMsg = pSipMsg;
1485 if (natSipAlgMsgFieldPos
1486 (pSipMsg, SIP_ALG_REMOTE_PARTY_ID, &pos,
1489 strlen(SIP_ALG_REMOTE_PARTY_ID);
1490 pTmpSipMsg = pSipMsg;
1491 natSipAlgMsgFieldPos(pTmpSipMsg,
1495 natSipAlgMsgFieldPos(pSipMsg,
1499 addrPortLen = pTmpSipMsg - pSipMsg;
1500 /* modify the field */
1502 natSipAlgModifyPayloadAddrPort
1503 (pSipMsg, &pSipMsgEnd, addrPortLen,
1504 &diffLen, modIp, modL4Port,
1505 ADDRESS_PORT_STRING);
1506 diffModSipLen += diffLen;
1508 printf("sip_alg_process: "
1509 "Remote-party-id is not in the msg\n");
1510 pSipMsg = pTmpSipMsg;
1513 /* Advance to SDP data message Owner address */
1514 if (natSipAlgMsgFieldPos
1515 (pSipMsg, SIP_ALG_OWNER, &pos,
1518 /* at start of owner string "o=" */
1519 pTmpSipMsg = pSipMsg;
1520 /* move tmmsg to CRLF of owner field */
1521 natSipAlgMsgFieldPosFindCrlf(pSipMsg,
1526 /* start of CRLF "/r/n" */
1527 /* move pSipMsg to IP address string in owner field */
1528 natSipAlgMsgFieldPos(pSipMsg,
1531 pSipMsg += (pos + strlen(SIP_ALG_IPV4));
1532 SKIP_SPACES(pSipMsg);
1533 /* after skipping spaces, pSip at start of addr */
1534 addrPortLen = pTmpSipMsg - pSipMsg;
1536 printf("sip_alg_processing: "
1537 "Invalid Owner field\n");
1540 /* Modify "Owner" field "addr" in payload. Input L4 port as 0 */
1542 natSipAlgModifyPayloadAddrPort(pSipMsg,
1547 ADDRESS_PORT_STRING);
1549 *diffModSipLen += diffLen;
1550 sdpMsgLen += diffLen;
1551 /* update the sdpMsgLen after modification */
1553 /* Advance to Connection information to modify IP address */
1554 if (natSipAlgMsgFieldPos
1555 (pSipMsg, SIP_ALG_CONN, &pos,
1558 pTmpSipMsg = pSipMsg;
1559 /* move tmmsg to CRLF of owner field */
1560 natSipAlgMsgFieldPosFindCrlf(pSipMsg,
1565 /* start of CRLF "/r/n" */
1566 /* move pSipMsg to IP address string in owner field */
1567 natSipAlgMsgFieldPos(pSipMsg,
1570 pSipMsg += (pos + strlen(SIP_ALG_IPV4));
1571 SKIP_SPACES(pSipMsg);
1572 /* after skipping spaces, pSip at start of addr */
1573 addrPortLen = pTmpSipMsg - pSipMsg;
1575 printf("sip_alg_processing: "
1576 "Invalid Connection field\n");
1579 /* Modify "Connection" field "addr" in payload. Input L4 port as 0 */
1581 natSipAlgModifyPayloadAddrPort(pSipMsg,
1586 ADDRESS_PORT_STRING);
1588 *diffModSipLen += diffLen;
1589 sdpMsgLen += diffLen;
1590 /* update the sdpMsgLen after modification */
1592 /* Advance to RTP audio port */
1593 if (natSipAlgMsgFieldPos
1594 (pSipMsg, SIP_ALG_AUDIO, &pos,
1597 (pos + strlen(SIP_ALG_AUDIO));
1598 SKIP_SPACES(pSipMsg);
1599 pTmpSipMsg = pSipMsg;
1600 natSipAlgMsgFieldPosFindSpace
1601 (pTmpSipMsg, SIP_ALG_SPACE, &pos,
1604 addrPortLen = pTmpSipMsg - pSipMsg;
1607 /* Modify "RTP Audio" port in payload. pass pub_ip as 0. */
1609 natSipAlgModifyPayloadAddrPort(pSipMsg,
1616 *diffModSipLen += diffLen;
1617 sdpMsgLen += diffLen;
1618 /* update the sdpMsgLen after modification */
1620 } else if (pkt_direction == PUBLIC
1621 && msgType == SIP_ALG_BYE_MSGTYPE) {
1622 /* Modify Bye URL (if its BYE), To field */
1624 /* need to modify address:Port in Bye message string. */
1625 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0);
1627 pTmpSipMsg = pSipMsg;
1628 natSipAlgMsgFieldPosFindSpace(pTmpSipMsg, SIP_ALG_SPACE,
1631 addrPortLen = pTmpSipMsg - pSipMsg;
1632 /* modify the "addr:port" in Bye message line */
1634 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1638 ADDRESS_PORT_STRING);
1639 *diffModSipLen += diffLen;
1640 /* increase the overall diff between old & mod sip msg */
1642 /* Advance to 'To" field */
1643 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1646 pTmpSipMsg = pSipMsg;
1647 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1650 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1653 addrPortLen = pTmpSipMsg - pSipMsg;
1655 natSipAlgModifyPayloadAddrPort(pSipMsg,
1661 ADDRESS_PORT_STRING);
1662 *diffModSipLen += diffLen;
1663 /* increase the overall diff between old & mod sip msg */
1666 ("sip_alg_processing: Invalid TO field\n");
1669 } else if (pkt_direction == PRIVATE
1670 && msgType == SIP_ALG_BYE_MSGTYPE) {
1671 /* change via and from field */
1673 /* Get to Via field IP address to modify */
1674 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
1676 /* advance to IP/Port string */
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,
1686 addrPortLen = pTmpSipMsg - pSipMsg;
1688 printf("sip_alg_process; No valid VIA field\n");
1691 /* Modify VIA field IP addr in payload */
1693 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1696 ADDRESS_PORT_STRING);
1697 *diffModSipLen = diffLen;
1699 /* Advance to "From" field IP addr in payload */
1700 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
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,
1709 diffLen = pTmpSipMsg - pSipMsg;
1710 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1711 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1714 /* now its pointing to start of From field "address:port" */
1715 addrPortLen = pTmpSipMsg - pSipMsg;
1718 ("sip_alg_process; No valid From field\n");
1721 /* Modify "From" field "addr:port" in payload */
1723 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1727 ADDRESS_PORT_STRING);
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 */
1735 /* Get to Via field IP address to modify */
1736 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
1738 /* advance to IP/Port string */
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,
1748 addrPortLen = pTmpSipMsg - pSipMsg;
1750 printf("sip_alg_process; No valid VIA field\n");
1753 /* Modify VIA field IP addr in payload */
1755 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1758 ADDRESS_PORT_STRING);
1759 *diffModSipLen = diffLen;
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,
1771 diffLen = pTmpSipMsg - pSipMsg;
1772 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1773 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1776 /* now its pointing to start of From field "address:port" */
1777 addrPortLen = pTmpSipMsg - pSipMsg;
1780 ("sip_alg_process; No valid From field\n");
1783 /* Modify "From" field "addr:port" in payload */
1785 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1789 ADDRESS_PORT_STRING);
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)
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,
1805 diffLen = pTmpSipMsg - pSipMsg;
1806 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1807 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1810 /* now its pointing to start of From field "address:port" */
1811 addrPortLen = pTmpSipMsg - pSipMsg;
1814 ("sip_alg_process; no valid from field\n");
1817 /* Modify "From" field "addr:port" in payload */
1818 pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg,
1823 ADDRESS_PORT_STRING);
1825 *diffModSipLen = diffLen;
1826 /* increase the overall diff between old & mod sip msg */
1828 /* Advance to "Contact" field */
1829 if (natSipAlgMsgFieldPos
1830 (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) {
1832 /* move tmpMsg to CRLF */
1833 pTmpSipMsg = pSipMsg;
1834 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1838 /* move sipMsg to addr:port string */
1839 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1842 addrPortLen = pTmpSipMsg - pSipMsg;
1844 printf("sip_alg_process; "
1845 "No valid Call Id field\n");
1848 /* Modify "Contact" field "addr:port" in payload */
1850 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1854 ADDRESS_PORT_STRING);
1856 *diffModSipLen += diffLen;
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);
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",
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;
1890 sdpMsgLen += sdpDataLen;
1891 tmpSdpLen = itoa(sdpMsgLen);
1892 int tmpStrLen = strlen(tmpSdpLen);
1894 /* move to Content length field & change the length to sipMsgLen */
1895 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0)
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,
1904 SKIP_SPACES(pSipMsg);
1905 diffLen = pTmpSipMsg - pSipMsg;
1906 natSipAlgAdjustMsg(pSipMsg, &pSipMsgEnd, tmpStrLen,
1908 strncpy(pSipMsg, tmpSdpLen, tmpStrLen);
1910 printf("sip_alg_process: Invalid Content Length\n");
1916 /* need to return toe start of the SIP msg */
1917 return pStartSipMsg;
1921 * Function to Fetch RTP & RTCP port & return. Invoked by CGNAT
1922 * while adding NAPT entry for RTP & RTCP
1924 int natSipAlgGetAudioPorts(struct rte_mbuf *pkt, uint16_t *rtpPort,
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;
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));
1937 /* Advance to check content type & get content length (SDP length) */
1938 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTYPE, &pos, 0) == FALSE)
1941 pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTYPE));
1942 SKIP_SPACES(pSipMsg);
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");
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);
1956 printf("sipAlggetAudioport - sdpMsgLen is 0\n");
1960 /* advance to RTP audio port */
1961 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AUDIO, &pos, 0) ==
1963 pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_AUDIO));
1964 SKIP_SPACES(pSipMsg);
1965 *rtpPort = strtol(pSipMsg, &pEndPtr, 10);
1969 /* advance to RTCP audio control port */
1970 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_RTCP, &pos, 0) ==
1972 pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_RTCP));
1973 SKIP_SPACES(pSipMsg);
1974 *rtcpPort = strtol(pSipMsg, &pEndPtr, 10);
1979 printf(" sipAlgGetAudioPort; rtpPort %d, rtcpPort %d\n",
1980 *rtpPort, *rtcpPort);
1984 /* function to find SPACES in ALG message */
1986 natSipAlgMsgFieldPosFindSpace(char *pData, const char *pIdStr, int *pPos,
1989 char *pStart = pData;
1996 searchLen = 1500; /* max default search length */
1999 while (*pData != ' ') {
2004 if (i > searchLen) {
2005 printf("SIP ALG Find Field Pos: "
2006 "Single message exceeds max len: %d\n",
2008 *pPos = searchLen; /* reaches the end */
2012 if (bcmp(pData, pIdStr, strlen(pIdStr)) == 0)
2016 *pPos = pData - pStart;
2020 /* function to find CRLF in ALG message */
2021 int natSipAlgMsgFieldPosFindCrlf(
2027 char *pStart = pData;
2034 searchLen = 1500; /* max default search length */
2037 while (*pData != '\r' && *(pData + 1) != '\n') {
2041 if (i >= searchLen) {
2042 printf("SIP ALG Find Field Pos: "
2043 " Single message exceeds max len: %d\n",
2045 *pPos = searchLen; /* reaches the end */
2049 if (bcmp(pData, pIdStr, strlen(pIdStr)) == 0)
2053 *pPos = pData - pStart;
2057 /* function to find field position in ALG message */
2058 int natSipAlgMsgFieldPos(char *pData,
2063 char *pStart = pData;
2070 searchLen = 1500; /* max default search length */
2073 while (*pData != '\r' && *(pData + 1) != '\n') {
2074 /* skip all space */
2076 while (*pData == ' ') {
2081 if (*pData == '\r' && *(pData + 1) == '\n')
2084 if (bcmp(pData, pIdStr, strlen(pIdStr)) == 0) {
2085 *pPos = pData - pStart;
2092 if (j >= searchLen) {
2093 *pPos = pData - pStart;
2099 /* advance to next line */
2101 for (i = 0; i < (searchLen - 1); i++) {
2102 if (pData[i] == '\r')
2103 if (pData[i + 1] == '\n')
2107 if (i > searchLen) {
2108 printf("SIP ALG Find Field Pos: "
2109 "Single message exceeds max len: %d\n",
2111 *pPos = searchLen; /* reaches the end */
2116 searchLen -= (i + 2);
2118 if ((pData[0] == '\r' && pData[1] == '\n') ||
2120 /* reach the end mark \r\n\r\n */
2122 if (searchLen > 0) {
2127 *pPos = pData - pStart;
2133 *pPos = pData - pStart;
2137 /* get SIP Call id string */
2138 char *getSipCallIdStr(char *pMsg)
2141 char *pCallId = NULL;
2145 for (i = 0; i < 200; i++) {
2152 printf("SIP_ALG: getCallid wrong string format\n");
2156 size_t size = RTE_CACHE_LINE_ROUNDUP(pMsg - pStart + 1);
2158 pCallId = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
2162 bcopy(pStart, pCallId, pMsg - pStart);
2163 *(pCallId + (pMsg - pStart)) = 0;
2166 printf("%s: %s\n", __func__, pCallId);
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)
2176 char addrport[MAX_ADDR_PORT_SIZE];
2177 struct in_addr ipAddr;
2178 uint32_t newStrLen = 0;
2179 char *tmpPort = NULL;
2182 tmpPort = itoa(modPort);
2185 if (type == ADDRESS_PORT_STRING) {
2186 ipAddr.s_addr = htonl(modIp);
2187 char *tmpAddr = inet_ntoa(ipAddr);
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);
2194 newStrLen = strlen(addrport);
2196 if (abs(newStrLen - oldStrLen) > 0) {
2198 * Call the function moving the SIP Msg pointer
2199 * to modify the field
2201 natSipAlgAdjustMsg(pSipMsg, pSipMsgEnd,
2202 newStrLen, oldStrLen);
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 */
2209 newStrLen = strlen(tmpPort);
2211 if (abs(newStrLen - oldStrLen) > 0) {
2213 * Call the function moving the SIP msg pointer
2214 * to modify the field
2216 natSipAlgAdjustMsg(pSipMsg, pSipMsgEnd,
2217 newStrLen, oldStrLen);
2220 /* replace the old port with new port */
2222 strncpy(pSipMsg, tmpPort, strlen(tmpPort));
2224 /* output difflen between old str len & modified new str length */
2225 if (newStrLen > oldStrLen)
2226 *diffLen = newStrLen - oldStrLen;
2228 return pSipMsg; /* modified SIP Msg */
2231 char *natSipAlgAdjustMsg(char *pSipMsg, char **pSipMsgEnd,
2232 uint32_t newStrLen, uint32_t oldStrLen)
2234 char MsgBuffer[MAX_SIP_UDP_MSG_SIZE];
2236 if (newStrLen > oldStrLen) {
2237 pSipMsg += oldStrLen;
2238 int msgLen = *pSipMsgEnd - pSipMsg;
2240 strncpy(MsgBuffer, pSipMsg, msgLen);
2241 pSipMsg += (newStrLen - oldStrLen);
2242 strncpy(pSipMsg, MsgBuffer, msgLen);
2245 printf("natSipAlgAdjustMsg: %u\n", msgLen);
2247 /* moving output end of SIP MSG by difflen like pSipMsg */
2248 *pSipMsgEnd += (newStrLen - oldStrLen);
2250 /* Setting space on the oldStr position */
2251 memset(pSipMsg, ' ', oldStrLen);