00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef NATHELPER_OPTIONS_H_
00028 #define NATHELPER_OPTIONS_H_
00029
00030 #include <stdlib.h>
00031 #include <string.h>
00032
00033 #include "../../parser/parse_rr.h"
00034 #include "../../str.h"
00035 #include "../../ut.h"
00036 #include "../../ip_addr.h"
00037
00038
00039 #define MAX_SIPPING_SIZE 65536
00040
00041
00042 #define append_fix( _p, _s) \
00043 do {\
00044 memcpy(_p, _s, sizeof(_s)-1);\
00045 _p += sizeof(_s)-1;\
00046 }while(0)
00047
00048
00049 static int sipping_fromtag = 0;
00050 static char sipping_callid_buf[8];
00051 static int sipping_callid_cnt = 0;
00052 static str sipping_callid = {0,0};
00053 static str sipping_from = {0,0};
00054 static str sipping_method = {"OPTIONS",7};
00055
00056
00057
00058 static void init_sip_ping(void)
00059 {
00060 int len;
00061 char *p;
00062
00063
00064 sipping_fromtag = rand();
00065
00066 len = 8;
00067 p = sipping_callid_buf;
00068 int2reverse_hex( &p, &len, rand() );
00069 sipping_callid.s = sipping_callid_buf;
00070 sipping_callid.len = 8-len;
00071
00072 sipping_callid_cnt = rand();
00073 }
00074
00075
00076
00077 static int sipping_rpl_filter(struct sip_msg *rpl)
00078 {
00079 struct cseq_body* cseq_b;
00080
00081
00082 if (parse_headers( rpl, HDR_VIA2_F, 0 )==-1 || (rpl->via2!=0))
00083 goto skip;
00084
00085
00086 if ( (!rpl->cseq && parse_headers(rpl,HDR_CSEQ_F,0)!=0) || rpl->cseq==0 ) {
00087 LM_ERR("failed to parse CSeq\n");
00088 goto error;
00089 }
00090 cseq_b = (struct cseq_body*)rpl->cseq->parsed;
00091 if (cseq_b->method.len!=sipping_method.len ||
00092 strncmp(cseq_b->method.s,sipping_method.s,sipping_method.len)!=0)
00093 goto skip;
00094
00095
00096 if ( (!rpl->callid && parse_headers(rpl,HDR_CALLID_F,0)!=0) ||
00097 rpl->callid==0 ) {
00098 LM_ERR("failed to parse Call-ID\n");
00099 goto error;
00100 }
00101 if ( rpl->callid->body.len<=sipping_callid.len+1 ||
00102 strncmp(rpl->callid->body.s,sipping_callid.s,sipping_callid.len)!=0 ||
00103 rpl->callid->body.s[sipping_callid.len]!='-')
00104 goto skip;
00105
00106 LM_DBG("reply for SIP natping filtered\n");
00107
00108
00109 return 0;
00110 skip:
00111 return 1;
00112 error:
00113 return -1;
00114 }
00115
00116
00117
00118
00119 static inline char* build_sipping(str *curi, struct socket_info* s, str *path,
00120 int *len_p)
00121 {
00122 #define s_len(_s) (sizeof(_s)-1)
00123 static char buf[MAX_SIPPING_SIZE];
00124 char *p;
00125 int len;
00126
00127 if ( sipping_method.len + 1 + curi->len + s_len(" SIP/2.0"CRLF) +
00128 s_len("Via: SIP/2.0/UDP ") + s->address_str.len +
00129 1 + s->port_no_str.len + s_len(";branch=0") +
00130 (path->len ? (s_len(CRLF"Route: ") + path->len) : 0) +
00131 s_len(CRLF"From: ") + sipping_from.len + s_len(";tag=") + 8 +
00132 s_len(CRLF"To: ") + curi->len +
00133 s_len(CRLF"Call-ID: ") + sipping_callid.len + 1 + 8 + 1 + 8 + 1 +
00134 s->address_str.len +
00135 s_len(CRLF"CSeq: 1 ") + sipping_method.len +
00136 s_len(CRLF"Content-Length: 0" CRLF CRLF)
00137 > MAX_SIPPING_SIZE )
00138 {
00139 LM_ERR("len exceeds %d\n",MAX_SIPPING_SIZE);
00140 return 0;
00141 }
00142
00143 p = buf;
00144 append_str( p, sipping_method.s, sipping_method.len);
00145 *(p++) = ' ';
00146 append_str( p, curi->s, curi->len);
00147 append_fix( p, " SIP/2.0"CRLF"Via: SIP/2.0/UDP ");
00148 append_str( p, s->address_str.s, s->address_str.len);
00149 *(p++) = ':';
00150 append_str( p, s->port_no_str.s, s->port_no_str.len);
00151 if (path->len) {
00152 append_fix( p, ";branch=0"CRLF"Route: ");
00153 append_str( p, path->s, path->len);
00154 append_fix( p, CRLF"From: ");
00155 } else {
00156 append_fix( p, ";branch=0"CRLF"From: ");
00157 }
00158 append_str( p, sipping_from.s, sipping_from.len);
00159 append_fix( p, ";tag=");
00160 len = 8;
00161 int2reverse_hex( &p, &len, sipping_fromtag++ );
00162 append_fix( p, CRLF"To: ");
00163 append_str( p, curi->s, curi->len);
00164 append_fix( p, CRLF"Call-ID: ");
00165 append_str( p, sipping_callid.s, sipping_callid.len);
00166 *(p++) = '-';
00167 len = 8;
00168 int2reverse_hex( &p, &len, sipping_callid_cnt++ );
00169 *(p++) = '-';
00170 len = 8;
00171 int2reverse_hex( &p, &len, get_ticks() );
00172 *(p++) = '@';
00173 append_str( p, s->address_str.s, s->address_str.len);
00174 append_fix( p, CRLF"CSeq: 1 ");
00175 append_str( p, sipping_method.s, sipping_method.len);
00176 append_fix( p, CRLF"Content-Length: 0" CRLF CRLF);
00177
00178 *len_p = p - buf;
00179 return buf;
00180 }
00181
00182
00183 #endif