e9eea6bc |
/*
|
61b50e2e |
* Copyright (C) 2005 Voice System SRL
*
|
27642a08 |
* This file is part of Kamailio, a free SIP server.
|
61b50e2e |
*
|
27642a08 |
* Kamailio is free software; you can redistribute it and/or modify
|
61b50e2e |
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
|
27642a08 |
* Kamailio is distributed in the hope that it will be useful,
|
61b50e2e |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
|
9e1ff448 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
61b50e2e |
*
*/
#ifndef NATHELPER_OPTIONS_H_
#define NATHELPER_OPTIONS_H_
#include <stdlib.h>
#include <string.h>
|
cf83221d |
#include "../../core/parser/parse_rr.h"
#include "../../core/str.h"
#include "../../core/ut.h"
#include "../../core/ip_addr.h"
|
e98a4ee5 |
#include "../../core/rand/kam_rand.h"
|
61b50e2e |
/* size of buffer used for building SIP PING req */
#define MAX_SIPPING_SIZE 65536
/* helping macros for building SIP PING ping request */
|
bcc5a668 |
#define append_fix(_p, _s) \
do { \
memcpy(_p, _s, sizeof(_s) - 1); \
_p += sizeof(_s) - 1; \
} while(0)
|
61b50e2e |
/* info used to generate SIP ping requests */
|
bcc5a668 |
static int sipping_fromtag = 0;
|
61b50e2e |
static char sipping_callid_buf[8];
|
bcc5a668 |
static int sipping_callid_cnt = 0;
static str sipping_callid = {0, 0};
static str sipping_from = STR_NULL;
static str sipping_method = str_init("OPTIONS");
|
61b50e2e |
|
351fc577 |
static void init_sip_ping(void)
|
61b50e2e |
{
int len;
char *p;
/* FROM tag - some random number */
|
e98a4ee5 |
sipping_fromtag = kam_rand();
|
61b50e2e |
/* callid fix part - hexa string */
len = 8;
p = sipping_callid_buf;
|
e98a4ee5 |
int2reverse_hex(&p, &len, kam_rand());
|
61b50e2e |
sipping_callid.s = sipping_callid_buf;
|
bcc5a668 |
sipping_callid.len = 8 - len;
|
61b50e2e |
/* callid counter part */
|
e98a4ee5 |
sipping_callid_cnt = kam_rand();
|
61b50e2e |
}
static int sipping_rpl_filter(struct sip_msg *rpl)
{
|
bcc5a668 |
struct cseq_body *cseq_b;
|
61b50e2e |
/* first check number of vias -> must be only one */
|
bcc5a668 |
if(parse_headers(rpl, HDR_VIA2_F, 0) == -1 || (rpl->via2 != 0))
|
61b50e2e |
goto skip;
/* check the method -> we need CSeq header */
|
bcc5a668 |
if((!rpl->cseq && parse_headers(rpl, HDR_CSEQ_F, 0) != 0)
|| rpl->cseq == 0) {
|
387847d7 |
LM_ERR("failed to parse CSeq\n");
|
61b50e2e |
goto error;
}
|
bcc5a668 |
cseq_b = (struct cseq_body *)rpl->cseq->parsed;
if(cseq_b->method.len != sipping_method.len
|| strncmp(cseq_b->method.s, sipping_method.s, sipping_method.len)
!= 0)
|
61b50e2e |
goto skip;
/* check constant part of callid */
|
bcc5a668 |
if((!rpl->callid && parse_headers(rpl, HDR_CALLID_F, 0) != 0)
|| rpl->callid == 0) {
|
387847d7 |
LM_ERR("failed to parse Call-ID\n");
|
61b50e2e |
goto error;
}
|
bcc5a668 |
if(rpl->callid->body.len <= sipping_callid.len + 1
|| strncmp(rpl->callid->body.s, sipping_callid.s,
sipping_callid.len)
!= 0
|| rpl->callid->body.s[sipping_callid.len] != '-')
|
61b50e2e |
goto skip;
|
387847d7 |
LM_DBG("reply for SIP natping filtered\n");
|
61b50e2e |
/* it's a reply to a SIP NAT ping -> absorb it and stop any
* further processing of it */
return 0;
skip:
return 1;
error:
return -1;
}
/* build the buffer of a SIP ping request */
|
bcc5a668 |
static inline char *build_sipping(str *curi, struct socket_info *s, str *path,
str *ruid, unsigned int aorhash, int *len_p)
|
61b50e2e |
{
|
bcc5a668 |
#define s_len(_s) (sizeof(_s) - 1)
|
1edb4298 |
#define MAX_BRANCHID 9999999
#define MIN_BRANCHID 1000000
|
bcc5a668 |
#define LEN_BRANCHID \
7 /* NOTE: this must be sync with the MX and MIN values !! */
|
61b50e2e |
static char buf[MAX_SIPPING_SIZE];
char *p;
int len;
|
4da31d56 |
str vaddr;
str vport;
|
ade1cad6 |
if(sipping_from.s==NULL || sipping_from.len<=0) {
LM_WARN("SIP ping enabled but no SIP ping From address\n");
return NULL;
}
|
bcc5a668 |
if(s->useinfo.name.len > 0)
|
4da31d56 |
vaddr = s->useinfo.name;
else
vaddr = s->address_str;
|
bcc5a668 |
if(s->useinfo.port_no > 0)
|
4da31d56 |
vport = s->useinfo.port_no_str;
else
vport = s->port_no_str;
|
61b50e2e |
|
bcc5a668 |
if(sipping_method.len + 1 + curi->len + s_len(" SIP/2.0" CRLF)
+ s_len("Via: SIP/2.0/UDP ") + vaddr.len
+ ((s->address.af == AF_INET6) ? 2 : 0) + 1 + vport.len
+ s_len(";branch=z9hG4bK") + LEN_BRANCHID
+ (path->len ? (s_len(CRLF "Route: ") + path->len) : 0)
+ s_len(CRLF "From: ") + sipping_from.len + s_len(";tag=")
+ ruid->len + 1 + 8 + 1 + 8 + s_len(CRLF "To: ") + curi->len
+ s_len(CRLF "Call-ID: ") + sipping_callid.len + 1 + 8 + 1
+ 8 + 1 + s->address_str.len + s_len(CRLF "CSeq: 1 ")
+ sipping_method.len
+ s_len(CRLF "Content-Length: 0" CRLF CRLF)
> MAX_SIPPING_SIZE) {
LM_ERR("len exceeds %d\n", MAX_SIPPING_SIZE);
|
61b50e2e |
return 0;
}
p = buf;
|
bcc5a668 |
append_str(p, sipping_method.s, sipping_method.len);
|
61b50e2e |
*(p++) = ' ';
|
bcc5a668 |
append_str(p, curi->s, curi->len);
append_fix(p, " SIP/2.0" CRLF "Via: SIP/2.0/UDP ");
if(s->address.af == AF_INET6) { /* Via header IP is a IPv6 reference */
append_fix(p, "[");
|
274f1034 |
}
|
bcc5a668 |
append_str(p, vaddr.s, vaddr.len);
if(s->address.af == AF_INET6) {
append_fix(p, "]");
|
274f1034 |
}
|
61b50e2e |
*(p++) = ':';
|
bcc5a668 |
append_str(p, vport.s, vport.len);
append_fix(p, ";branch=z9hG4bK");
int2bstr((long)(rand() / (float)RAND_MAX * (MAX_BRANCHID - MIN_BRANCHID)
+ MIN_BRANCHID),
p + LEN_BRANCHID - INT2STR_MAX_LEN + 1, NULL);
|
1edb4298 |
p += LEN_BRANCHID;
|
bcc5a668 |
if(path->len) {
append_fix(p, CRLF "Route: ");
append_str(p, path->s, path->len);
|
5a57095f |
}
|
bcc5a668 |
append_fix(p, CRLF "From: ");
append_str(p, sipping_from.s, sipping_from.len);
append_fix(p, ";tag=");
append_str(p, ruid->s, ruid->len);
|
ae8f15dc |
*(p++) = '-';
len = 8;
|
bcc5a668 |
int2reverse_hex(&p, &len, aorhash);
|
ae8f15dc |
*(p++) = '-';
|
61b50e2e |
len = 8;
|
bcc5a668 |
int2reverse_hex(&p, &len, sipping_fromtag++);
append_fix(p, CRLF "To: ");
append_str(p, curi->s, curi->len);
append_fix(p, CRLF "Call-ID: ");
append_str(p, sipping_callid.s, sipping_callid.len);
|
61b50e2e |
*(p++) = '-';
len = 8;
|
bcc5a668 |
int2reverse_hex(&p, &len, sipping_callid_cnt++);
|
61b50e2e |
*(p++) = '-';
len = 8;
|
bcc5a668 |
int2reverse_hex(&p, &len, get_ticks());
|
61b50e2e |
*(p++) = '@';
|
bcc5a668 |
append_str(p, s->address_str.s, s->address_str.len);
append_fix(p, CRLF "CSeq: 1 ");
append_str(p, sipping_method.s, sipping_method.len);
append_fix(p, CRLF "Content-Length: 0" CRLF CRLF);
|
61b50e2e |
*len_p = p - buf;
return buf;
}
|
ade1cad6 |
#endif
|