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);
168 int len = n == 0 ? 1 : floor(log10l(labs(n))) + 1;
171 len++; /* room for negative sign '-' */
173 snprintf(itoa_buf, len + 1, "%ld", n);
174 return (char *)&itoa_buf;
177 struct sip_alg_table_entry *retrieve_sip_alg_entry(
178 struct sip_alg_key *alg_key);
180 struct sip_alg_table_entry *retrieve_sip_alg_entry(
181 struct sip_alg_key *alg_key)
183 struct sip_alg_table_entry *sip_alg_data = NULL;
185 int ret = rte_hash_lookup(sip_alg_hash_table, alg_key);
189 printf("alg-hash lookup failed ret %d, "
190 "EINVAL %d, ENOENT %d\n",
191 ret, EINVAL, ENOENT);
194 sip_alg_data = sip_alg_table[ret];
201 //int remove_sip_alg_entry(uint32_t ipaddr, uint16_t portid);
202 int remove_sip_alg_entry(uint32_t ipaddr, uint16_t portid)
204 struct sip_alg_key alg_key;
205 void *sip_alg_entry_data;
208 alg_key.l4port = portid;
209 alg_key.ip_address = ipaddr;
214 printf("remove_sip_entry ip %x, port %d\n", alg_key.ip_address,
217 ret = rte_hash_lookup(sip_alg_hash_table, &alg_key);
220 printf("removesipalgentry: "
221 "rtehashlookup failed with error %d",
226 sip_alg_entry_data = sip_alg_table[ret];
228 free(sip_alg_entry_data);
229 rte_hash_del_key(sip_alg_hash_table, &alg_key);
235 * Function for populating SIP ALG entry. return 0 - success &
236 * return -1 - failure
238 int populate_sip_alg_entry(uint32_t ipaddr, uint16_t portid,
239 char *sip_call_id, uint8_t call_direction,
240 enum sip_alg_port_type port_type);
241 int populate_sip_alg_entry(uint32_t ipaddr, uint16_t portid,
242 char *sip_call_id, uint8_t call_direction,
243 enum sip_alg_port_type port_type)
245 struct sip_alg_key alg_key;
247 alg_key.l4port = portid;
248 alg_key.ip_address = ipaddr;
254 printf("populate_sip_alg_entry port %d, ip %x\n",
255 alg_key.l4port, alg_key.ip_address);
257 struct sip_alg_table_entry *new_alg_data =
258 retrieve_sip_alg_entry(&alg_key);
262 printf("sip_alg_entry exists ip%x, port %d\n",
263 alg_key.ip_address, alg_key.l4port);
268 new_alg_data = (struct sip_alg_table_entry *)
269 malloc(sizeof(struct sip_alg_table_entry));
270 if (new_alg_data == NULL) {
271 printf("populate sip alg entry: allocation failed\n");
275 new_alg_data->l4port = portid;
276 new_alg_data->ip_address = ipaddr;
277 new_alg_data->l4port_type = port_type;
278 new_alg_data->sip_alg_call_direction = call_direction;
279 strcpy((char *)new_alg_data->sip_alg_call_id, (char *)sip_call_id);
280 new_alg_data->filler1 = 0;
281 new_alg_data->filler2 = 0;
282 new_alg_data->filler3 = 0;
284 ret = rte_hash_add_key(sip_alg_hash_table, &alg_key);
286 printf("populate sip - rte_hash_add_key_data ERROR %d\n", ret);
291 sip_alg_table[ret] = new_alg_data;
294 printf("SIP_ALG: table update - ip=%x on port=%d ret=%d\n",
295 alg_key.ip_address, portid, ret);
300 int sip_alg_dpi(struct rte_mbuf *pkt, enum pkt_dir pkt_direction,
301 uint32_t modIp, uint16_t modL4Port,
302 uint32_t pubIp, uint16_t pubL4Port,
303 uint16_t modRtpPort, uint16_t modRtcpPort)
305 uint16_t msgType = 0;
306 enum sip_alg_call_direction call_direction = 0;
307 uint32_t ip_address = 0;
310 struct ipv4_hdr *ip_h;
311 struct ether_hdr *eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
312 struct udp_hdr *udp_h;
313 char *pSipMsg = NULL;
314 struct sip_alg_table_entry *sip_alg_entry;
315 char *sip_call_id = NULL;
317 struct sip_alg_key alg_key;
318 uint16_t diffModSipLen = 0;
320 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
321 udp_h = (struct udp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
322 pSipMsg = ((char *)udp_h + sizeof(struct udp_hdr));
325 printf("%s: packet length(%u), buffer length(%u)\n", __func__,
326 rte_pktmbuf_pkt_len(pkt), pkt->buf_len);
327 printf("%s: last segment addr(%p %p)\n", __func__,
328 rte_pktmbuf_lastseg(pkt), pkt);
329 printf("%s: data len(%u, %u)\n", __func__, rte_pktmbuf_data_len(pkt),
330 rte_pktmbuf_data_len(rte_pktmbuf_lastseg(pkt)));
331 printf("%s: buffer addr(%p), data_off(%u), nb_segs(%u)\n", __func__,
332 pkt->buf_addr, pkt->data_off, pkt->nb_segs);
335 if (IS_STRING_SAME(pSipMsg, SIP_ALG_INVITE)) {
336 /* find the call id position in the message */
337 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CALLID, &pos, 0) ==
340 getSipCallIdStr(pSipMsg + pos +
341 TAG_TO_DATAPOS(SIP_ALG_CALLID));
343 printf("sip_call_id returned is NULL\n");
348 printf("sipalgdpi: %d call id %s\n", __LINE__,
351 if (pkt_direction == PRIVATE) {
352 call_direction = SIP_CALL_OUTGOING;
353 ip_address = rte_bswap32(ip_h->src_addr);
354 port = rte_bswap16(udp_h->src_port);
355 } else if (pkt_direction == PUBLIC) {
356 call_direction = SIP_CALL_INCOMING;
362 printf("0=>sip_alg_dpi: pkt_dir(%d), call_dir(%d), "
363 "ipaddr(%x) port(%x)\n",
364 pkt_direction, call_direction, ip_address, port);
366 /* add 3 entries in ALG table for SIP, RTP, RTCP */
367 ret = populate_sip_alg_entry(ip_address, port,
368 sip_call_id, call_direction,
371 printf("sipalgdpi:populate SIP alg UDP entry failed\n");
374 if (modRtpPort != 0) {
375 ret = populate_sip_alg_entry(ip_address, modRtpPort,
377 call_direction, SIP_RTP);
380 "populate SIP alg entry RTP failed\n");
384 if (modRtcpPort != 0) {
385 ret = populate_sip_alg_entry(ip_address, modRtcpPort,
387 call_direction, SIP_RTCP);
390 "populate SIP alg entry RTCP failed\n");
395 /* Call ALG packet process function for checking & payload modification */
397 sip_alg_process(pkt, pkt_direction, call_direction,
398 SIP_ALG_INVITE_MSGTYPE, modIp, modL4Port, 0,
399 0, modRtpPort, modRtcpPort, &diffModSipLen);
402 * not SIP INVITE, could be SIP response 200 OK invite, 100 trying,
403 * 180 ringing or BYE or 200 OK BYe
405 /* retrieve ALG entry from SIP ALG table */
406 if (pkt_direction == PRIVATE) {
407 alg_key.ip_address = rte_bswap32(ip_h->src_addr);
408 alg_key.l4port = rte_bswap16(udp_h->src_port);
410 alg_key.ip_address = pubIp;
411 alg_key.l4port = pubL4Port;
416 sip_alg_entry = retrieve_sip_alg_entry(&alg_key);
419 printf("%s: sip_alg_entry_ptr(%p)\n", __func__,
421 printf("1=>%s: pkt_dir(%d), modIp(%x),modL4Port(%x), "
422 "modRtpPort(%x), modRtcpPort(%x), pubIp(%x), pubL4Port(%x)\n",
423 __func__, pkt_direction, modIp, modL4Port,
424 modRtpPort, modRtcpPort, pubIp, pubL4Port);
428 call_direction = sip_alg_entry->sip_alg_call_direction;
429 if (IS_STRING_SAME(pSipMsg, SIP_ALG_BYE) ||
430 IS_STRING_SAME(pSipMsg, SIP_ALG_CANCEL)) {
431 msgType = SIP_ALG_BYE_MSGTYPE;
434 } else if (IS_STRING_SAME(pSipMsg, SIP_ALG_ACK)) {
435 msgType = SIP_ALG_ACK_MSGTYPE;
441 /* checking if its OK or Trying or Ringing */
442 if (IS_STRING_SAME(pSipMsg, SIP_ALG_200_OK)) {
443 /* check CSEQ. Based on that update the msg type */
444 if (natSipAlgMsgFieldPos
445 (pSipMsg, SIP_ALG_CSEQ, &pos, 0) == TRUE) {
450 TAG_TO_DATAPOS(SIP_ALG_CSEQ);
452 /* skip the number field */
456 if (IS_STRING_SAME(pBye, SIP_ALG_BYE)
459 (pBye, SIP_ALG_CANCEL)))
461 SIP_ALG_200_OK_BYE_MSGTYPE;
465 SIP_ALG_200_OK_INVITE_MSGTYPE;
467 } else if (IS_STRING_SAME(pSipMsg, SIP_ALG_TRYING) ||
468 IS_STRING_SAME(pSipMsg, SIP_ALG_RINGING)) {
469 msgType = SIP_ALG_TRYING_RINGING_MSGTYPE;
474 printf("2=>%s: pkt_dir(%d), call_dir(%d), "
475 "msgType(%d), modIp(%x), modL4Port(%x), "
476 " modRtpPort(%x), modRtcpPort(%x)\n",
477 __func__, pkt_direction, call_direction,
478 msgType, modIp, modL4Port, modRtpPort,
480 /* Call SIP alg processing for further processing. */
482 sip_alg_process(pkt, pkt_direction, call_direction,
483 msgType, modIp, modL4Port, pubIp,
484 pubL4Port, modRtpPort, modRtcpPort,
491 printf("%s: Before IP total length(%u), udp length(%u)\n", __func__,
492 rte_bswap16(ip_h->total_length), rte_bswap16(udp_h->dgram_len));
494 * need to modify mbuf & modified length of payload in the IP/UDP
495 * header length fields and return to CGNAT for transmitting
498 if (diffModSipLen > 0) {
499 len = rte_bswap16(udp_h->dgram_len);
500 len += diffModSipLen;
501 udp_h->dgram_len = rte_bswap16(len);
503 len = rte_bswap16(ip_h->total_length);
504 len += diffModSipLen;
505 ip_h->total_length = rte_bswap16(len);
507 if (rte_pktmbuf_append(pkt, diffModSipLen) == NULL)
508 printf("%s: pktmbuf_append returns NULL", __func__);
513 printf("%s: After IP total length(%u), udp length(%u), "
514 "diffModSipLen(%u)\n", __func__,
515 rte_bswap16(ip_h->total_length),
516 rte_bswap16(udp_h->dgram_len),
525 char *sip_alg_process(struct rte_mbuf *pkt, uint16_t pkt_direction,
526 uint16_t call_direction, uint16_t msgType, uint32_t modIp,
527 uint16_t modL4Port, uint32_t pubIp, uint16_t pubL4Port,
528 uint16_t modRtpPort, uint16_t modRtcpPort,
529 uint16_t *diffModSipLen)
531 struct ipv4_hdr *ip_h;
532 struct ether_hdr *eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
533 struct udp_hdr *udp_h;
534 char *pSipMsg, *pStr, *pEndPtr;
536 /* diff between old & new modified field len */
537 uint32_t diffLen, addrPortLen;
541 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
542 udp_h = (struct udp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
543 pSipMsg = ((char *)udp_h + sizeof(struct udp_hdr));
544 char *pTmpSipMsg = pSipMsg;
545 char *pStartSipMsg = pSipMsg;
548 rte_bswap16(ip_h->total_length) - sizeof(struct ipv4_hdr) -
549 sizeof(struct udp_hdr);
551 if (natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0) ==
553 pTmpSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN));
555 printf("sip_alg_process: Invalid Content Length\n");
559 SKIP_SPACES(pTmpSipMsg);
560 int sdpDataLen = strtol(pTmpSipMsg, &pStr, 10);
562 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg, SIP_ALG_DOUBLE_CRLF, &pos, 0);
563 pTmpSipMsg += (pos + strlen(SIP_ALG_DOUBLE_CRLF));
566 if (natSipAlgMsgFieldPos
567 (pTmpSipMsg, SIP_ALG_REMOTE_PARTY_ID, &pos, 0) == TRUE) {
568 pTmpSipMsg += pos + strlen(SIP_ALG_REMOTE_PARTY_ID);
569 /* move further to CRLF which is the end of SIP msg */
570 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
571 SIP_ALG_DOUBLE_CRLF, &pos,
573 pTmpSipMsg += (pos + strlen(SIP_ALG_DOUBLE_CRLF));
576 int sipMsgLen = (pTmpSipMsg - pSipMsg);
578 if ((sipMsgLen + sdpDataLen) > strlen(pSipMsg))
581 char *pSipMsgEnd = pSipMsg + sipMsgLen + sdpDataLen;
584 printf("%s: pSipMsg: %p, pSipMsgEnd: %p, sipMsgLen: %d, "
585 "sdpDataLen: %d totalSipMsgLen: %d\n",
586 __func__, pSipMsg, pSipMsgEnd, sipMsgLen, sdpDataLen,
589 if (call_direction == SIP_CALL_OUTGOING) {
590 if ((msgType == SIP_ALG_INVITE_MSGTYPE)
591 || (msgType == SIP_ALG_ACK_MSGTYPE)) {
592 /* Get to Via field IP address/Port to modify */
593 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
595 /* advance to IP/Port string */
597 (pos + strlen(SIP_ALG_VIA) +
598 SIP_ALG_VIA_FIELD_IPADDR);
599 pTmpSipMsg = pSipMsg;
600 /* move pTmp to next field */
601 natSipAlgMsgFieldPos(pTmpSipMsg,
602 SIP_ALG_SEMICOLON, &pos,
605 addrPortLen = pTmpSipMsg - pSipMsg;
607 printf("sip_alg_process; No valid VIA field\n");
610 /* Modify VIA field IP addr:port in payload */
612 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
616 ADDRESS_PORT_STRING);
618 *diffModSipLen += diffLen;
619 /* increase the overall diff between old & mod sip msg */
621 /* Advance to "From" field IP addr in payload */
622 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
624 pSipMsg += pos; /* Moving to "From" */
625 /* advance to IP/Port string */
626 pTmpSipMsg = pSipMsg;
627 /* move pTmpSipMsg to str ">" which is end of add:port string */
628 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
631 diffLen = pTmpSipMsg - pSipMsg;
632 /* find "@" from "From" string to ">" string which is start of "addr:port" */
633 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
636 /* now its pointing to start of From field "address:port" */
637 addrPortLen = pTmpSipMsg - pSipMsg;
640 ("sip_alg_process; No valid From field\n");
643 /* Modify "From" field "addr:port" in payload */
645 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
649 ADDRESS_PORT_STRING);
651 *diffModSipLen += diffLen;
652 /* increase the overall diff between old & mod sip msg */
654 /* Advance to Call id field */
655 if (natSipAlgMsgFieldPos
656 (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
658 /* moving it to start of string "Call-ID" */
659 pTmpSipMsg = pSipMsg;
660 /* move tmpSipMsg to next field */
661 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
665 diffLen = pTmpSipMsg - pSipMsg;
666 /* Move pSipMsg to start of Call id "IP addr" string */
667 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
670 addrPortLen = pTmpSipMsg - pSipMsg;
672 printf("sip_alg_process; "
673 " No valid Call Id field\n");
676 /* Modify "Call-id" field "addr:port" in payload */
677 /* L4 port input is made as 0 as its only addr string modification */
679 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
682 ADDRESS_PORT_STRING);
684 *diffModSipLen += diffLen;
686 /* Advance to "Contact" field */
687 if (natSipAlgMsgFieldPos
688 (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) {
690 /* move tmpMsg to CRLF */
691 pTmpSipMsg = pSipMsg;
692 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
696 /* move sipMsg to addr:port string */
697 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
700 addrPortLen = pTmpSipMsg - pSipMsg;
703 printf("sip_alg_process; "
704 "No valid Call Id field\n");
707 /* Modify "Contact" field "addr:port" in payload */
709 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
713 ADDRESS_PORT_STRING);
715 *diffModSipLen += diffLen;
717 if (msgType == SIP_ALG_INVITE_MSGTYPE) {
718 /* Advance to check content type & get content length (SDP length) */
719 if (natSipAlgMsgFieldPos
720 (pSipMsg, SIP_ALG_CONTYPE, &pos,
724 TAG_TO_DATAPOS(SIP_ALG_CONTYPE));
725 SKIP_SPACES(pSipMsg);
726 /*check the application/sdp type, if not, exit */
728 (pSipMsg, SIP_ALG_APPSDP)) {
729 printf("sip_alg_process "
730 "Invalid Content type\n");
734 printf("sip_alg_process; "
735 "No valid Content field\n");
739 /* get the SDP content length */
740 natSipAlgMsgFieldPos(pSipMsg,
741 SIP_ALG_CONTENT_LEN, &pos,
744 (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN));
745 SKIP_SPACES(pSipMsg);
746 sdpMsgLen = strtol(pSipMsg, &pEndPtr, 10);
748 /* if ACK message, SDP content wont be there.go to ALG process complete */
749 if (msgType == SIP_ALG_ACK_MSGTYPE)
750 goto sipAlgProcessExit;
752 printf("sip_alg_process - "
757 /* Advance to SDP data message Owner address */
758 if (natSipAlgMsgFieldPos
759 (pSipMsg, SIP_ALG_OWNER, &pos,
762 /* at start of owner string "o=" */
763 pTmpSipMsg = pSipMsg;
764 /* move tmmsg to CRLF of owner field */
765 natSipAlgMsgFieldPosFindCrlf(pSipMsg,
770 /* start of CRLF "/r/n" */
771 /* move pSipMsg to IP address string in owner field */
772 natSipAlgMsgFieldPos(pSipMsg,
775 pSipMsg += (pos + strlen(SIP_ALG_IPV4));
776 SKIP_SPACES(pSipMsg);
777 /* after skipping spaces, pSip at start of addr */
778 addrPortLen = pTmpSipMsg - pSipMsg;
780 printf("sip_alg_processing: "
781 "Invalid Owner field\n");
784 /* Modify "Owner" field "addr" in payload. Input L4 port as 0 */
786 natSipAlgModifyPayloadAddrPort(pSipMsg,
791 ADDRESS_PORT_STRING);
793 *diffModSipLen += diffLen;
794 sdpMsgLen += diffLen;
795 /* need to adjust the SDP msg len as modification done. */
797 /* Advance to Connection information to modify IP address */
798 if (natSipAlgMsgFieldPos
799 (pSipMsg, SIP_ALG_CONN, &pos,
802 pTmpSipMsg = pSipMsg;
803 /* move tmmsg to CRLF of owner field */
804 natSipAlgMsgFieldPosFindCrlf(pSipMsg,
809 /* start of CRLF "/r/n" */
810 /* move pSipMsg to IP address string in owner field */
811 natSipAlgMsgFieldPos(pSipMsg,
814 pSipMsg += (pos + strlen(SIP_ALG_IPV4));
815 SKIP_SPACES(pSipMsg);
816 /* after skipping spaces, pSip at start of addr */
817 addrPortLen = pTmpSipMsg - pSipMsg;
819 printf("sip_alg_processing: "
820 "Invalid Owner field\n");
823 /* Modify "Connection" field "addr" in payload. Input L4 port as 0 */
825 natSipAlgModifyPayloadAddrPort(pSipMsg,
830 ADDRESS_PORT_STRING);
832 *diffModSipLen += diffLen;
833 sdpMsgLen += diffLen;
834 /* need to adjust the SDP msg len as modification done. */
836 /* Advance to RTP audio port */
837 if (natSipAlgMsgFieldPos
838 (pSipMsg, SIP_ALG_AUDIO, &pos,
842 TAG_TO_DATAPOS(SIP_ALG_AUDIO));
843 SKIP_SPACES(pSipMsg);
844 pTmpSipMsg = pSipMsg;
845 natSipAlgMsgFieldPosFindSpace
846 (pTmpSipMsg, SIP_ALG_SPACE, &pos,
849 addrPortLen = pTmpSipMsg - pSipMsg;
852 /* Modify "RTP Audio" port in payload. pass pub_ip as 0. */
854 natSipAlgModifyPayloadAddrPort(pSipMsg,
861 *diffModSipLen += diffLen;
862 sdpMsgLen += diffLen;
863 /* need to adjust the SDP msg len as modification done. */
865 /* Advance to RTCP control port, if its there */
866 if (natSipAlgMsgFieldPos
867 (pSipMsg, SIP_ALG_RTCP, &pos,
871 TAG_TO_DATAPOS(SIP_ALG_RTCP));
872 SKIP_SPACES(pSipMsg);
873 pTmpSipMsg = pSipMsg;
874 natSipAlgMsgFieldPosFindSpace
875 (pTmpSipMsg, SIP_ALG_SPACE, &pos,
878 addrPortLen = pTmpSipMsg - pSipMsg;
880 /* Modify "RTP Audio" port in payload. pass pub_ip as 0. */
882 natSipAlgModifyPayloadAddrPort
883 (pSipMsg, &pSipMsgEnd, addrPortLen,
884 &diffLen, 0, modRtcpPort,
887 *diffModSipLen += diffLen;
888 sdpMsgLen += diffLen;
889 /* need to adjust the SDP msg len as modification done. */
892 /* with this SIP payload modification is complete for outbound invite message */
893 } else if ((msgType == SIP_ALG_TRYING_RINGING_MSGTYPE)
894 || (msgType == SIP_ALG_200_OK_INVITE_MSGTYPE)) {
895 /* Get to Via field IP address/Port to modify */
896 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
898 /* advance to IP/Port string */
900 (pos + strlen(SIP_ALG_VIA) +
901 SIP_ALG_VIA_FIELD_IPADDR);
902 pTmpSipMsg = pSipMsg;
903 /* move pTmp to next field */
904 natSipAlgMsgFieldPos(pTmpSipMsg,
905 SIP_ALG_SEMICOLON, &pos,
908 addrPortLen = pTmpSipMsg - pSipMsg;
910 printf("sip_alg_process; No valid VIA field\n");
913 /* Modify VIA field IP addr:port in payload */
915 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
919 ADDRESS_PORT_STRING);
920 *diffModSipLen = diffLen;
922 /* Advance to "From" field IP addr in payload */
923 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
925 pSipMsg += pos; /* Moving to "From" */
926 /* advance to IP/Port string */
927 pTmpSipMsg = pSipMsg;
928 /* move pTmpSipMsg to str ">" which is end of add:port string */
929 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
932 //diffLen = pTmpSipMsg - pSipMsg;
933 /* find "@" from "From" string to ">" string which is start of "addr:port" */
934 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
937 /* now its pointing to start of From field "address:port" */
938 addrPortLen = pTmpSipMsg - pSipMsg;
941 ("sip_alg_process; No valid From field\n");
944 /* Modify "From" field "addr:port" in payload */
946 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
950 ADDRESS_PORT_STRING);
952 *diffModSipLen += diffLen;
953 /* increase the overall diff between old & mod sip msg */
955 /* Advance to Call id field */
956 if (natSipAlgMsgFieldPos
957 (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
959 /* moving it to start of string "Call-ID" */
960 pTmpSipMsg = pSipMsg;
961 /* move tmpSipMsg to next field */
962 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
966 //diffLen = pTmpSipMsg - pSipMsg;
967 /* Move pSipMsg to start of Call id "IP addr" string */
968 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
971 addrPortLen = pTmpSipMsg - pSipMsg;
973 printf("sip_alg_process; "
974 "No valid Call Id field\n");
977 /* Modify "Call-id" field "addr" in payload */
978 /* L4 port input is made as 0 as its only addr string modification */
980 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
983 ADDRESS_PORT_STRING);
985 *diffModSipLen += diffLen;
987 } else if (pkt_direction == PRIVATE
988 && msgType == SIP_ALG_BYE_MSGTYPE) {
989 /* change via, from, call-id and contact field */
991 /* Get to Via field IP address to modify */
992 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
994 /* advance to IP/Port string */
996 (pos + strlen(SIP_ALG_VIA) +
997 SIP_ALG_VIA_FIELD_IPADDR);
998 pTmpSipMsg = pSipMsg;
999 /* move pTmp to next field */
1000 natSipAlgMsgFieldPos(pTmpSipMsg,
1001 SIP_ALG_SEMICOLON, &pos,
1004 addrPortLen = pTmpSipMsg - pSipMsg;
1006 printf("sip_alg_process; No valid VIA field\n");
1009 /* Modify VIA field IP addr in payload */
1011 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1014 ADDRESS_PORT_STRING);
1015 *diffModSipLen = diffLen;
1017 /* Advance to "From" field IP addr in payload */
1018 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
1020 pSipMsg += pos; /* Moving to "From" */
1021 /* advance to IP/Port string */
1022 pTmpSipMsg = pSipMsg;
1023 /* move pTmpSipMsg to str ">" which is end of add:port string */
1024 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1027 diffLen = pTmpSipMsg - pSipMsg;
1028 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1029 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1032 /* now its pointing to start of From field "address:port" */
1033 addrPortLen = pTmpSipMsg - pSipMsg;
1036 ("sip_alg_process; No valid From field\n");
1039 /* Modify "From" field "addr:port" in payload */
1041 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1045 ADDRESS_PORT_STRING);
1047 *diffModSipLen += diffLen;
1048 /* increase the overall diff between old & mod sip msg */
1050 /* Advance to Call id field */
1051 if (natSipAlgMsgFieldPos
1052 (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
1054 /* moving it to start of string "Call-ID" */
1055 pTmpSipMsg = pSipMsg;
1056 /* move tmpSipMsg to next field */
1057 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1061 diffLen = pTmpSipMsg - pSipMsg;
1062 /* Move pSipMsg to start of Call id "IP addr" string */
1063 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1066 addrPortLen = pTmpSipMsg - pSipMsg;
1068 printf("sip_alg_process; "
1069 "No valid Call Id field\n");
1072 /* Modify "Call-id" field "addr:port" in payload */
1073 /* L4 port input is made as 0 as its only addr string modification */
1075 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1078 ADDRESS_PORT_STRING);
1080 *diffModSipLen += diffLen;
1082 /* Advance to "Contact" field */
1083 if (natSipAlgMsgFieldPos
1084 (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) {
1086 /* move tmpMsg to semicolon */
1087 pTmpSipMsg = pSipMsg;
1088 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1089 SIP_ALG_CRLF, &pos, 0);
1091 /* move sipMsg to addr:port string */
1093 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT,
1098 goto SipMsgAdvance2;
1100 addrPortLen = pTmpSipMsg - pSipMsg;
1103 printf("sip_alg_process; "
1104 "No valid Call Id field\n");
1107 /* Modify "Contact" field "addr:port" in payload */
1109 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1113 ADDRESS_PORT_STRING);
1115 *diffModSipLen += diffLen;
1116 } else if (pkt_direction == PUBLIC
1117 && msgType == SIP_ALG_BYE_MSGTYPE) {
1119 * Modify Bye URL (if its BYE), To field,
1120 * Call-Id if call triggered from private, then modify
1123 /* need to modify address:Port in Bye message string. */
1124 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0);
1126 pTmpSipMsg = pSipMsg;
1127 natSipAlgMsgFieldPosFindSpace(pTmpSipMsg, SIP_ALG_SPACE,
1130 addrPortLen = pTmpSipMsg - pSipMsg;
1131 /* modify the "addr:port" in Bye message line */
1133 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1137 ADDRESS_PORT_STRING);
1138 *diffModSipLen += diffLen;
1139 /* increase the overall diff between old & mod sip msg */
1141 /* Advance to 'To" field */
1142 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1145 pTmpSipMsg = pSipMsg;
1146 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1149 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1152 addrPortLen = pTmpSipMsg - pSipMsg;
1154 natSipAlgModifyPayloadAddrPort(pSipMsg,
1160 ADDRESS_PORT_STRING);
1161 *diffModSipLen += diffLen;
1162 /* increase the overall diff between old & mod sip msg */
1165 /* check for Call-Id. */
1166 if (natSipAlgMsgFieldPos
1167 (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
1169 /* moving it to start of string "Call-ID" */
1170 pTmpSipMsg = pSipMsg;
1171 /* move tmpSipMsg to next field */
1172 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1176 //diffLen = pTmpSipMsg - pSipMsg;
1177 /* Move pSipMsg to start of Call id "IP addr" string */
1178 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1181 addrPortLen = pTmpSipMsg - pSipMsg;
1183 printf("sip_alg_process; "
1184 "No valid Call Id field\n");
1187 /* Modify "Call-id" field "addr" in payload */
1188 /* L4 port input is made as 0 as its only addr string modification */
1190 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1193 ADDRESS_PORT_STRING);
1195 *diffModSipLen += diffLen;
1196 } else if (pkt_direction == PRIVATE
1197 && (msgType == SIP_ALG_200_OK_BYE_MSGTYPE)) {
1199 * Need to modify To field, Call-Id,
1200 * Contact if call triggered from private, then modify
1202 /* Get to To field IP address to modify */
1203 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1205 pSipMsg += pos; /* Moving to "From" */
1206 /* advance to IP/Port string */
1207 pTmpSipMsg = pSipMsg;
1208 /* move pTmpSipMsg to str ">" which is end of add:port string */
1209 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1212 diffLen = pTmpSipMsg - pSipMsg;
1213 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1214 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1217 /* now its pointing to start of From field "address:port" */
1218 addrPortLen = pTmpSipMsg - pSipMsg;
1221 ("sip_alg_process; no valid from field\n");
1224 /* Modify "From" field "addr:port" in payload */
1226 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1230 ADDRESS_PORT_STRING);
1232 *diffModSipLen = diffLen;
1233 /* increase the overall diff between old & mod sip msg */
1235 /* Advance to "Contact" field */
1236 if (natSipAlgMsgFieldPos
1237 (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) {
1239 /* move tmpMsg to CRLF */
1240 pTmpSipMsg = pSipMsg;
1241 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1245 /* move sipMsg to addr:port string */
1247 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT,
1252 goto SipMsgAdvance2;
1254 addrPortLen = pTmpSipMsg - pSipMsg;
1256 printf("sip_alg_process; "
1257 "No valid Call Id field\n");
1260 /* Modify "Contact" field "addr:port" in payload */
1262 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1266 ADDRESS_PORT_STRING);
1268 *diffModSipLen += diffLen;
1269 } else if (pkt_direction == PUBLIC
1270 && (msgType == SIP_ALG_200_OK_BYE_MSGTYPE)) {
1271 /* change via and from field, call-id field */
1273 /* Get to Via field IP address to modify */
1274 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
1276 /* advance to IP/Port string */
1278 (pos + strlen(SIP_ALG_VIA) +
1279 SIP_ALG_VIA_FIELD_IPADDR);
1280 pTmpSipMsg = pSipMsg;
1281 /* move pTmp to next field */
1282 natSipAlgMsgFieldPos(pTmpSipMsg,
1283 SIP_ALG_SEMICOLON, &pos,
1286 addrPortLen = pTmpSipMsg - pSipMsg;
1288 printf("sip_alg_process; No valid VIA field\n");
1291 /* Modify VIA field IP addr in payload */
1293 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1296 ADDRESS_PORT_STRING);
1297 *diffModSipLen = diffLen;
1299 /* Advance to "From" field IP addr in payload */
1300 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
1302 pSipMsg += pos; /* Moving to "From" */
1303 /* advance to IP/Port string */
1304 pTmpSipMsg = pSipMsg;
1305 /* move pTmpSipMsg to str ">" which is end of add:port string */
1306 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1309 diffLen = pTmpSipMsg - pSipMsg;
1310 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1311 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1314 /* now its pointing to start of From field "address:port" */
1315 addrPortLen = pTmpSipMsg - pSipMsg;
1318 ("sip_alg_process; No valid From field\n");
1321 /* Modify "From" field "addr:port" in payload */
1323 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1327 ADDRESS_PORT_STRING);
1329 *diffModSipLen += diffLen;
1331 /* check for Call-Id. */
1332 if (natSipAlgMsgFieldPos
1333 (pSipMsg, SIP_ALG_CALLID, &pos, 0) == TRUE) {
1335 /* Call id 'addr" need to modified. */
1336 pTmpSipMsg = pSipMsg;
1337 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1341 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1344 addrPortLen = pTmpSipMsg - pSipMsg;
1345 /* modify call id "addr" */
1347 natSipAlgModifyPayloadAddrPort(pSipMsg,
1352 ADDRESS_PORT_STRING);
1354 *diffModSipLen += diffLen;
1355 /* increase the overall diff between old & mod sip msg */
1357 printf("sip_alg_process; "
1358 "no valid Call-id field\n");
1361 /* increase the overall diff between old & mod sip msg */
1363 } else if (call_direction == SIP_CALL_INCOMING) {
1364 if ((msgType == SIP_ALG_INVITE_MSGTYPE)
1365 || (msgType == SIP_ALG_ACK_MSGTYPE)) {
1366 /* need to modify Invite RL, TO field */
1367 /* move to Invite RL IP address string */
1368 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0)
1371 pTmpSipMsg = pSipMsg;
1372 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_SIP,
1374 pTmpSipMsg += (pos - 1);
1375 /* pointing to space before SIP/2.0 */
1376 addrPortLen = pTmpSipMsg - pSipMsg;
1379 ("sip_alg_process: %d Invalid Invite RL\n",
1383 /* modify Invite RL URI in payload */
1385 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1389 ADDRESS_PORT_STRING);
1390 *diffModSipLen += diffLen;
1391 /* increase the overall diff between old & mod sip msg */
1393 /* Advance to 'To" field */
1394 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1397 pTmpSipMsg = pSipMsg;
1398 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1401 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1404 addrPortLen = pTmpSipMsg - pSipMsg;
1406 printf("sip_alg_processing; "
1407 "%d Invalid To field\n",
1411 /* Modify TO field IP addr:port in payload */
1413 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1417 ADDRESS_PORT_STRING);
1418 *diffModSipLen += diffLen;
1419 /* increase the overall diff between old & mod sip msg */
1420 } else if ((msgType == SIP_ALG_TRYING_RINGING_MSGTYPE)
1421 || (msgType == SIP_ALG_200_OK_INVITE_MSGTYPE)) {
1422 /* Need to modify TO field */
1423 /* Advance to 'To" field */
1424 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1427 pTmpSipMsg = pSipMsg;
1428 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1431 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1434 addrPortLen = pTmpSipMsg - pSipMsg;
1436 natSipAlgModifyPayloadAddrPort(pSipMsg,
1442 ADDRESS_PORT_STRING);
1443 *diffModSipLen += diffLen;
1444 /* increase the overall diff between old & mod sip msg */
1446 if (msgType == SIP_ALG_200_OK_INVITE_MSGTYPE) {
1447 /* need to modify Contact, Remote-Party Id, SDP O=IN, C=IN, Audio Port */
1448 /* Advance to "Contact" field */
1450 if (natSipAlgMsgFieldPos
1451 (pSipMsg, SIP_ALG_CONTACT, &pos,
1454 /* move tmpMsg to CRLF */
1455 pTmpSipMsg = pSipMsg;
1456 natSipAlgMsgFieldPos(pTmpSipMsg,
1460 /* move sipMsg to addr:port string */
1462 if (natSipAlgMsgFieldPos(pSipMsg,
1471 addrPortLen = pTmpSipMsg - pSipMsg;
1473 printf("sip_alg_process; "
1474 "No valid Call Id field\n");
1477 /* Modify "Contact" field "addr:port" in payload */
1479 natSipAlgModifyPayloadAddrPort(pSipMsg,
1485 ADDRESS_PORT_STRING);
1487 *diffModSipLen += diffLen;
1489 /* advance to Remote-Party Id */
1490 pTmpSipMsg = pSipMsg;
1491 if (natSipAlgMsgFieldPos
1492 (pSipMsg, SIP_ALG_REMOTE_PARTY_ID, &pos,
1495 strlen(SIP_ALG_REMOTE_PARTY_ID);
1496 pTmpSipMsg = pSipMsg;
1497 natSipAlgMsgFieldPos(pTmpSipMsg,
1501 natSipAlgMsgFieldPos(pSipMsg,
1505 addrPortLen = pTmpSipMsg - pSipMsg;
1506 /* modify the field */
1508 natSipAlgModifyPayloadAddrPort
1509 (pSipMsg, &pSipMsgEnd, addrPortLen,
1510 &diffLen, modIp, modL4Port,
1511 ADDRESS_PORT_STRING);
1512 diffModSipLen += diffLen;
1514 printf("sip_alg_process: "
1515 "Remote-party-id is not in the msg\n");
1516 pSipMsg = pTmpSipMsg;
1519 /* Advance to SDP data message Owner address */
1520 if (natSipAlgMsgFieldPos
1521 (pSipMsg, SIP_ALG_OWNER, &pos,
1524 /* at start of owner string "o=" */
1525 pTmpSipMsg = pSipMsg;
1526 /* move tmmsg to CRLF of owner field */
1527 natSipAlgMsgFieldPosFindCrlf(pSipMsg,
1532 /* start of CRLF "/r/n" */
1533 /* move pSipMsg to IP address string in owner field */
1534 natSipAlgMsgFieldPos(pSipMsg,
1537 pSipMsg += (pos + strlen(SIP_ALG_IPV4));
1538 SKIP_SPACES(pSipMsg);
1539 /* after skipping spaces, pSip at start of addr */
1540 addrPortLen = pTmpSipMsg - pSipMsg;
1542 printf("sip_alg_processing: "
1543 "Invalid Owner field\n");
1546 /* Modify "Owner" field "addr" in payload. Input L4 port as 0 */
1548 natSipAlgModifyPayloadAddrPort(pSipMsg,
1553 ADDRESS_PORT_STRING);
1555 *diffModSipLen += diffLen;
1556 sdpMsgLen += diffLen;
1557 /* update the sdpMsgLen after modification */
1559 /* Advance to Connection information to modify IP address */
1560 if (natSipAlgMsgFieldPos
1561 (pSipMsg, SIP_ALG_CONN, &pos,
1564 pTmpSipMsg = pSipMsg;
1565 /* move tmmsg to CRLF of owner field */
1566 natSipAlgMsgFieldPosFindCrlf(pSipMsg,
1571 /* start of CRLF "/r/n" */
1572 /* move pSipMsg to IP address string in owner field */
1573 natSipAlgMsgFieldPos(pSipMsg,
1576 pSipMsg += (pos + strlen(SIP_ALG_IPV4));
1577 SKIP_SPACES(pSipMsg);
1578 /* after skipping spaces, pSip at start of addr */
1579 addrPortLen = pTmpSipMsg - pSipMsg;
1581 printf("sip_alg_processing: "
1582 "Invalid Connection field\n");
1585 /* Modify "Connection" field "addr" in payload. Input L4 port as 0 */
1587 natSipAlgModifyPayloadAddrPort(pSipMsg,
1592 ADDRESS_PORT_STRING);
1594 *diffModSipLen += diffLen;
1595 sdpMsgLen += diffLen;
1596 /* update the sdpMsgLen after modification */
1598 /* Advance to RTP audio port */
1599 if (natSipAlgMsgFieldPos
1600 (pSipMsg, SIP_ALG_AUDIO, &pos,
1603 (pos + strlen(SIP_ALG_AUDIO));
1604 SKIP_SPACES(pSipMsg);
1605 pTmpSipMsg = pSipMsg;
1606 natSipAlgMsgFieldPosFindSpace
1607 (pTmpSipMsg, SIP_ALG_SPACE, &pos,
1610 addrPortLen = pTmpSipMsg - pSipMsg;
1613 /* Modify "RTP Audio" port in payload. pass pub_ip as 0. */
1615 natSipAlgModifyPayloadAddrPort(pSipMsg,
1622 *diffModSipLen += diffLen;
1623 sdpMsgLen += diffLen;
1624 /* update the sdpMsgLen after modification */
1626 } else if (pkt_direction == PUBLIC
1627 && msgType == SIP_ALG_BYE_MSGTYPE) {
1628 /* Modify Bye URL (if its BYE), To field */
1630 /* need to modify address:Port in Bye message string. */
1631 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos, 0);
1633 pTmpSipMsg = pSipMsg;
1634 natSipAlgMsgFieldPosFindSpace(pTmpSipMsg, SIP_ALG_SPACE,
1637 addrPortLen = pTmpSipMsg - pSipMsg;
1638 /* modify the "addr:port" in Bye message line */
1640 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1644 ADDRESS_PORT_STRING);
1645 *diffModSipLen += diffLen;
1646 /* increase the overall diff between old & mod sip msg */
1648 /* Advance to 'To" field */
1649 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1652 pTmpSipMsg = pSipMsg;
1653 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1656 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1659 addrPortLen = pTmpSipMsg - pSipMsg;
1661 natSipAlgModifyPayloadAddrPort(pSipMsg,
1667 ADDRESS_PORT_STRING);
1668 *diffModSipLen += diffLen;
1669 /* increase the overall diff between old & mod sip msg */
1672 ("sip_alg_processing: Invalid TO field\n");
1675 } else if (pkt_direction == PRIVATE
1676 && msgType == SIP_ALG_BYE_MSGTYPE) {
1677 /* change via and from field */
1679 /* Get to Via field IP address to modify */
1680 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
1682 /* advance to IP/Port string */
1684 (pos + strlen(SIP_ALG_VIA) +
1685 SIP_ALG_VIA_FIELD_IPADDR);
1686 pTmpSipMsg = pSipMsg;
1687 /* move pTmp to next field */
1688 natSipAlgMsgFieldPos(pTmpSipMsg,
1689 SIP_ALG_SEMICOLON, &pos,
1692 addrPortLen = pTmpSipMsg - pSipMsg;
1694 printf("sip_alg_process; No valid VIA field\n");
1697 /* Modify VIA field IP addr in payload */
1699 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1702 ADDRESS_PORT_STRING);
1703 *diffModSipLen = diffLen;
1705 /* Advance to "From" field IP addr in payload */
1706 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_FROM, &pos, 0)
1708 pSipMsg += pos; /* Moving to "From" */
1709 /* advance to IP/Port string */
1710 pTmpSipMsg = pSipMsg;
1711 /* move pTmpSipMsg to str ">" which is end of add:port string */
1712 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1715 diffLen = pTmpSipMsg - pSipMsg;
1716 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1717 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1720 /* now its pointing to start of From field "address:port" */
1721 addrPortLen = pTmpSipMsg - pSipMsg;
1724 ("sip_alg_process; No valid From field\n");
1727 /* Modify "From" field "addr:port" in payload */
1729 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1733 ADDRESS_PORT_STRING);
1735 *diffModSipLen += diffLen;
1736 /* increase the overall diff between old & mod sip msg */
1737 } else if (pkt_direction == PRIVATE
1738 && msgType == SIP_ALG_200_OK_BYE_MSGTYPE) {
1739 /* change via and from field */
1741 /* Get to Via field IP address to modify */
1742 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_VIA, &pos, 0)
1744 /* advance to IP/Port string */
1746 (pos + strlen(SIP_ALG_VIA) +
1747 SIP_ALG_VIA_FIELD_IPADDR);
1748 pTmpSipMsg = pSipMsg;
1749 /* move pTmp to next field */
1750 natSipAlgMsgFieldPos(pTmpSipMsg,
1751 SIP_ALG_SEMICOLON, &pos,
1754 addrPortLen = pTmpSipMsg - pSipMsg;
1756 printf("sip_alg_process; No valid VIA field\n");
1759 /* Modify VIA field IP addr in payload */
1761 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1764 ADDRESS_PORT_STRING);
1765 *diffModSipLen = diffLen;
1767 /* Advance to "From" field IP addr in payload */
1768 if (natSipAlgMsgFieldPos(pSipMsg,
1769 SIP_ALG_FROM, &pos, 0) == TRUE) {
1770 pSipMsg += pos; /* Moving to "From" */
1771 /* advance to IP/Port string */
1772 pTmpSipMsg = pSipMsg;
1773 /* move pTmpSipMsg to str ">" which is end of add:port string */
1774 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1777 diffLen = pTmpSipMsg - pSipMsg;
1778 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1779 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1782 /* now its pointing to start of From field "address:port" */
1783 addrPortLen = pTmpSipMsg - pSipMsg;
1786 ("sip_alg_process; No valid From field\n");
1789 /* Modify "From" field "addr:port" in payload */
1791 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1795 ADDRESS_PORT_STRING);
1797 *diffModSipLen += diffLen;
1798 /* increase the overall diff between old & mod sip msg */
1799 } else if (pkt_direction == PUBLIC
1800 && msgType == SIP_ALG_200_OK_BYE_MSGTYPE) {
1801 /* Get to To field IP address to modify */
1802 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_TO, &pos, 0)
1804 pSipMsg += pos; /* Moving to "From" */
1805 /* advance to IP/Port string */
1806 pTmpSipMsg = pSipMsg;
1807 /* move pTmpSipMsg to str ">" which is end of add:port string */
1808 natSipAlgMsgFieldPos(pTmpSipMsg, SIP_ALG_GREAT,
1811 diffLen = pTmpSipMsg - pSipMsg;
1812 /* find "@" from "From" string to ">" string which is start of "addr:port" */
1813 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1816 /* now its pointing to start of From field "address:port" */
1817 addrPortLen = pTmpSipMsg - pSipMsg;
1820 ("sip_alg_process; no valid from field\n");
1823 /* Modify "From" field "addr:port" in payload */
1824 pSipMsg = natSipAlgModifyPayloadAddrPort(pSipMsg,
1829 ADDRESS_PORT_STRING);
1831 *diffModSipLen = diffLen;
1832 /* increase the overall diff between old & mod sip msg */
1834 /* Advance to "Contact" field */
1835 if (natSipAlgMsgFieldPos
1836 (pSipMsg, SIP_ALG_CONTACT, &pos, 0) == TRUE) {
1838 /* move tmpMsg to CRLF */
1839 pTmpSipMsg = pSipMsg;
1840 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1844 /* move sipMsg to addr:port string */
1845 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AT, &pos,
1848 addrPortLen = pTmpSipMsg - pSipMsg;
1850 printf("sip_alg_process; "
1851 "No valid Call Id field\n");
1854 /* Modify "Contact" field "addr:port" in payload */
1856 natSipAlgModifyPayloadAddrPort(pSipMsg, &pSipMsgEnd,
1860 ADDRESS_PORT_STRING);
1862 *diffModSipLen += diffLen;
1867 /* need to remove the SIP ALG entry if msg is 200 OK BYE response */
1868 if (call_direction == SIP_CALL_OUTGOING) {
1869 /* call remove sip alg entry here */
1870 if (pkt_direction == PRIVATE) {
1871 if (msgType == SIP_ALG_200_OK_BYE_MSGTYPE) {
1872 if (remove_sip_alg_entry
1873 (rte_bswap32(ip_h->src_addr),
1874 rte_bswap16(udp_h->src_port)) < 0)
1875 printf("removesipalgentry failed: "
1876 "ipaddr %d, portid %d\n",
1877 ip_h->src_addr, udp_h->src_port);
1881 if (pkt_direction == PUBLIC) {
1882 if (msgType == SIP_ALG_200_OK_BYE_MSGTYPE) {
1883 if (remove_sip_alg_entry(pubIp, pubL4Port) < 0)
1884 printf("removesipalgentry failed: "
1885 " ipaddr %d, portid %d\n",
1891 /* adjust SDP msg len (sdpMsgLen) in the content length field of SIP msg */
1892 if ((sdpMsgLen > 0) && (sdpDataLen > 0)) {
1893 pSipMsg = pStartSipMsg;
1894 char *tmpSdpLen = NULL;
1896 sdpMsgLen += sdpDataLen;
1897 tmpSdpLen = itoa(sdpMsgLen);
1900 tmpStrLen = strlen(tmpSdpLen);
1904 /* move to Content length field & change the length to sipMsgLen */
1905 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0)
1907 pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN));
1908 SKIP_SPACES(pSipMsg);
1909 pTmpSipMsg = pSipMsg;
1910 natSipAlgMsgFieldPosFindCrlf(pTmpSipMsg,
1911 SIP_ALG_DOUBLE_CRLF, &pos,
1914 SKIP_SPACES(pSipMsg);
1915 diffLen = pTmpSipMsg - pSipMsg;
1916 natSipAlgAdjustMsg(pSipMsg, &pSipMsgEnd, tmpStrLen,
1918 strncpy(pSipMsg, tmpSdpLen, tmpStrLen);
1920 printf("sip_alg_process: Invalid Content Length\n");
1926 /* need to return toe start of the SIP msg */
1927 return pStartSipMsg;
1931 * Function to Fetch RTP & RTCP port & return. Invoked by CGNAT
1932 * while adding NAPT entry for RTP & RTCP
1934 int natSipAlgGetAudioPorts(struct rte_mbuf *pkt, uint16_t *rtpPort,
1937 struct ipv4_hdr *ip_h;
1938 struct ether_hdr *eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
1939 struct udp_hdr *udp_h;
1940 char *pSipMsg, *pEndPtr;
1943 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1944 udp_h = (struct udp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1945 pSipMsg = ((char *)udp_h + sizeof(struct udp_hdr));
1947 /* Advance to check content type & get content length (SDP length) */
1948 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTYPE, &pos, 0) == FALSE)
1951 pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTYPE));
1952 SKIP_SPACES(pSipMsg);
1954 /*check the application/sdp type, if not, exit */
1955 if (!IS_STRING_SAME(pSipMsg, SIP_ALG_APPSDP)) {
1956 printf("sip_alg_getAudioPort Invalid Content type\n");
1960 /* get the SDP content length */
1961 natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0);
1962 pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_CONTENT_LEN));
1963 SKIP_SPACES(pSipMsg);
1964 sdpMsgLen = strtol(pSipMsg, &pEndPtr, 10);
1966 printf("sipAlggetAudioport - sdpMsgLen is 0\n");
1970 /* advance to RTP audio port */
1971 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_AUDIO, &pos, 0) ==
1973 pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_AUDIO));
1974 SKIP_SPACES(pSipMsg);
1975 *rtpPort = strtol(pSipMsg, &pEndPtr, 10);
1979 /* advance to RTCP audio control port */
1980 if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_RTCP, &pos, 0) ==
1982 pSipMsg += (pos + TAG_TO_DATAPOS(SIP_ALG_RTCP));
1983 SKIP_SPACES(pSipMsg);
1984 *rtcpPort = strtol(pSipMsg, &pEndPtr, 10);
1989 printf(" sipAlgGetAudioPort; rtpPort %d, rtcpPort %d\n",
1990 *rtpPort, *rtcpPort);
1994 /* function to find SPACES in ALG message */
1996 natSipAlgMsgFieldPosFindSpace(char *pData, const char *pIdStr, int *pPos,
1999 char *pStart = pData;
2006 searchLen = 1500; /* max default search length */
2009 while (*pData != ' ') {
2014 if (i > searchLen) {
2015 printf("SIP ALG Find Field Pos: "
2016 "Single message exceeds max len: %d\n",
2018 *pPos = searchLen; /* reaches the end */
2022 if (bcmp(pData, pIdStr, strlen(pIdStr)) == 0)
2026 *pPos = pData - pStart;
2030 /* function to find CRLF in ALG message */
2031 int natSipAlgMsgFieldPosFindCrlf(
2037 char *pStart = pData;
2044 searchLen = 1500; /* max default search length */
2047 while (*pData != '\r' && *(pData + 1) != '\n') {
2051 if (i >= searchLen) {
2052 printf("SIP ALG Find Field Pos: "
2053 " Single message exceeds max len: %d\n",
2055 *pPos = searchLen; /* reaches the end */
2059 if (bcmp(pData, pIdStr, strlen(pIdStr)) == 0)
2063 *pPos = pData - pStart;
2067 /* function to find field position in ALG message */
2068 int natSipAlgMsgFieldPos(char *pData,
2073 char *pStart = pData;
2080 searchLen = 1500; /* max default search length */
2083 while (*pData != '\r' && *(pData + 1) != '\n') {
2084 /* skip all space */
2086 while (*pData == ' ') {
2091 if (*pData == '\r' && *(pData + 1) == '\n')
2094 if (bcmp(pData, pIdStr, strlen(pIdStr)) == 0) {
2095 *pPos = pData - pStart;
2102 if (j >= searchLen) {
2103 *pPos = pData - pStart;
2109 /* advance to next line */
2111 for (i = 0; i < (searchLen - 1); i++) {
2112 if (pData[i] == '\r')
2113 if (pData[i + 1] == '\n')
2117 if (i > searchLen) {
2118 printf("SIP ALG Find Field Pos: "
2119 "Single message exceeds max len: %d\n",
2121 *pPos = searchLen; /* reaches the end */
2126 searchLen -= (i + 2);
2128 if ((pData[0] == '\r' && pData[1] == '\n') ||
2130 /* reach the end mark \r\n\r\n */
2132 if (searchLen > 0) {
2137 *pPos = pData - pStart;
2143 *pPos = pData - pStart;
2147 /* get SIP Call id string */
2148 char *getSipCallIdStr(char *pMsg)
2151 char *pCallId = NULL;
2155 for (i = 0; i < 200; i++) {
2162 printf("SIP_ALG: getCallid wrong string format\n");
2166 size_t size = RTE_CACHE_LINE_ROUNDUP(pMsg - pStart + 1);
2168 pCallId = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
2172 bcopy(pStart, pCallId, pMsg - pStart);
2173 *(pCallId + (pMsg - pStart)) = 0;
2176 printf("%s: %s\n", __func__, pCallId);
2181 char *natSipAlgModifyPayloadAddrPort(
2182 char *pSipMsg, char **pSipMsgEnd,
2183 uint32_t oldStrLen, uint32_t *diffLen,
2184 uint32_t modIp, uint16_t modPort, uint32_t type)
2186 char addrport[MAX_ADDR_PORT_SIZE];
2187 struct in_addr ipAddr;
2188 uint32_t newStrLen = 0;
2189 char *tmpPort = NULL;
2192 tmpPort = itoa(modPort);
2195 if (type == ADDRESS_PORT_STRING) {
2196 ipAddr.s_addr = htonl(modIp);
2197 char *tmpAddr = inet_ntoa(ipAddr);
2199 if (modPort != 0) /* for addr:port combo modification */
2200 sprintf(addrport, "%s:%s", tmpAddr, tmpPort);
2201 else /* if only address modification */
2202 sprintf(addrport, "%s", tmpAddr);
2204 newStrLen = strlen(addrport);
2206 if (abs(newStrLen - oldStrLen) > 0) {
2208 * Call the function moving the SIP Msg pointer
2209 * to modify the field
2211 natSipAlgAdjustMsg(pSipMsg, pSipMsgEnd,
2212 newStrLen, oldStrLen);
2215 /* replace the old addr:port with new addr:port */
2216 strncpy(pSipMsg, addrport, strlen(addrport));
2217 } else if (type == PORT_STRING) { /* only port modification */
2219 newStrLen = strlen(tmpPort);
2221 if (abs(newStrLen - oldStrLen) > 0) {
2223 * Call the function moving the SIP msg pointer
2224 * to modify the field
2226 natSipAlgAdjustMsg(pSipMsg, pSipMsgEnd,
2227 newStrLen, oldStrLen);
2230 /* replace the old port with new port */
2232 strncpy(pSipMsg, tmpPort, strlen(tmpPort));
2234 /* output difflen between old str len & modified new str length */
2235 if (newStrLen > oldStrLen)
2236 *diffLen = newStrLen - oldStrLen;
2241 return pSipMsg; /* modified SIP Msg */
2244 char *natSipAlgAdjustMsg(char *pSipMsg, char **pSipMsgEnd,
2245 uint32_t newStrLen, uint32_t oldStrLen)
2247 char MsgBuffer[MAX_SIP_UDP_MSG_SIZE];
2249 if (newStrLen > oldStrLen) {
2250 pSipMsg += oldStrLen;
2251 int msgLen = *pSipMsgEnd - pSipMsg;
2253 strncpy(MsgBuffer, pSipMsg, msgLen);
2254 pSipMsg += (newStrLen - oldStrLen);
2255 strncpy(pSipMsg, MsgBuffer, msgLen);
2258 printf("natSipAlgAdjustMsg: %u\n", msgLen);
2260 /* moving output end of SIP MSG by difflen like pSipMsg */
2261 *pSipMsgEnd += (newStrLen - oldStrLen);
2263 /* Setting space on the oldStr position */
2264 memset(pSipMsg, ' ', oldStrLen);