aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authorfile <file@f38db490-d61c-443f-a65b-d21fe96a405b>2006-10-17 20:30:34 +0000
committerfile <file@f38db490-d61c-443f-a65b-d21fe96a405b>2006-10-17 20:30:34 +0000
commit9009267bb9a0e4b4f706d91c67c23c762e71d5a1 (patch)
treea385d3270329a2dc060258c269d28a85c9d90b83 /channels
parent7268d40ab9da9f123c885756ab7db48817efe657 (diff)
Don't create a "real" pvt structure for requests that shouldn't be able to create one. Instead use a temporary pvt and fill it with enough information so we can send a reply.
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@45378 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_sip.c101
1 files changed, 77 insertions, 24 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index a5d1d4d6f..7291353fd 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -146,6 +146,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/localtime.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/compiler.h"
+#include "asterisk/threadstorage.h"
#ifndef FALSE
#define FALSE 0
@@ -347,23 +348,24 @@ static const struct cfsip_methods {
enum sipmethod id;
int need_rtp; /*!< when this is the 'primary' use for a pvt structure, does it need RTP? */
char * const text;
+ int can_create;
} sip_methods[] = {
- { SIP_UNKNOWN, RTP, "-UNKNOWN-" },
- { SIP_RESPONSE, NO_RTP, "SIP/2.0" },
- { SIP_REGISTER, NO_RTP, "REGISTER" },
- { SIP_OPTIONS, NO_RTP, "OPTIONS" },
- { SIP_NOTIFY, NO_RTP, "NOTIFY" },
- { SIP_INVITE, RTP, "INVITE" },
- { SIP_ACK, NO_RTP, "ACK" },
- { SIP_PRACK, NO_RTP, "PRACK" },
- { SIP_BYE, NO_RTP, "BYE" },
- { SIP_REFER, NO_RTP, "REFER" },
- { SIP_SUBSCRIBE, NO_RTP, "SUBSCRIBE" },
- { SIP_MESSAGE, NO_RTP, "MESSAGE" },
- { SIP_UPDATE, NO_RTP, "UPDATE" },
- { SIP_INFO, NO_RTP, "INFO" },
- { SIP_CANCEL, NO_RTP, "CANCEL" },
- { SIP_PUBLISH, NO_RTP, "PUBLISH" }
+ { SIP_UNKNOWN, RTP, "-UNKNOWN-", 0 },
+ { SIP_RESPONSE, NO_RTP, "SIP/2.0", 0 },
+ { SIP_REGISTER, NO_RTP, "REGISTER", 1 },
+ { SIP_OPTIONS, NO_RTP, "OPTIONS", 1 },
+ { SIP_NOTIFY, NO_RTP, "NOTIFY", 0 },
+ { SIP_INVITE, RTP, "INVITE", 1 },
+ { SIP_ACK, NO_RTP, "ACK", 0 },
+ { SIP_PRACK, NO_RTP, "PRACK", 0 },
+ { SIP_BYE, NO_RTP, "BYE", 0 },
+ { SIP_REFER, NO_RTP, "REFER", 0 },
+ { SIP_SUBSCRIBE, NO_RTP, "SUBSCRIBE", 1 },
+ { SIP_MESSAGE, NO_RTP, "MESSAGE", 1 },
+ { SIP_UPDATE, NO_RTP, "UPDATE", 0 },
+ { SIP_INFO, NO_RTP, "INFO", 0 },
+ { SIP_CANCEL, NO_RTP, "CANCEL", 0 },
+ { SIP_PUBLISH, NO_RTP, "PUBLISH", 1 }
};
/*! Define SIP option tags, used in Require: and Supported: headers
@@ -551,7 +553,6 @@ static int regobjs = 0; /*!< Registry objects */
static struct ast_flags global_flags[2] = {{0}}; /*!< global SIP_ flags */
-
/*! \brief Protect the SIP dialog list (of sip_pvt's) */
AST_MUTEX_DEFINE_STATIC(iflock);
@@ -1145,6 +1146,9 @@ static struct ast_register_list {
int recheck;
} regl;
+/*! \brief A per-thread temporary pvt structure */
+AST_THREADSTORAGE(ts_temp_pvt, temp_pvt_init);
+
/*! \todo Move the sip_auth list to AST_LIST */
static struct sip_auth *authl = NULL; /*!< Authentication list for realm authentication */
@@ -1190,6 +1194,7 @@ static int __sip_reliable_xmit(struct sip_pvt *p, int seqno, int resp, char *dat
static int __transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
static int retrans_pkt(void *data);
static int transmit_sip_request(struct sip_pvt *p, struct sip_request *req);
+static int transmit_response_using_temp(ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg);
static int transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req);
static int transmit_response_reliable(struct sip_pvt *p, const char *msg, const struct sip_request *req);
static int transmit_response_with_date(struct sip_pvt *p, const char *msg, const struct sip_request *req);
@@ -4201,7 +4206,7 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
Called by handle_request, sipsock_read */
static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method)
{
- struct sip_pvt *p;
+ struct sip_pvt *p = NULL;
char *tag = ""; /* note, tag is never NULL */
char totag[128];
char fromtag[128];
@@ -4267,13 +4272,13 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si
}
ast_mutex_unlock(&iflock);
- /* If this is a response and we have ignoring of out of dialog responses turned on, then drop it */
- if (req->method == SIP_RESPONSE)
- return NULL;
-
- /* Allocate new call */
- if ((p = sip_alloc(callid, sin, 1, intended_method)))
+ /* See if the method is capable of creating a dialog */
+ if (!sip_methods[intended_method].can_create) {
+ if (intended_method != SIP_RESPONSE)
+ transmit_response_using_temp(callid, sin, 1, intended_method, req, "481 Call leg/transaction does not exist");
+ } else if ((p = sip_alloc(callid, sin, 1, intended_method))) {
ast_mutex_lock(&p->lock);
+ }
return p;
}
@@ -5559,6 +5564,54 @@ static int __transmit_response(struct sip_pvt *p, const char *msg, const struct
return send_response(p, &resp, reliable, seqno);
}
+/*! \brief Transmit response, no retransmits, using a temporary pvt structure */
+static int transmit_response_using_temp(ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg)
+{
+ struct sip_pvt *p = NULL;
+
+ if (!(p = ast_threadstorage_get(&ts_temp_pvt, sizeof(*p)))) {
+ ast_log(LOG_NOTICE, "Failed to get temporary pvt\n");
+ return -1;
+ }
+
+ memset(p, 0, sizeof(*p));
+
+ /* Initialize the bare minimum */
+ if (ast_string_field_init(p, 512))
+ return -1;
+
+ p->method = intended_method;
+
+ if (sin) {
+ p->sa = *sin;
+ if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
+ p->ourip = __ourip;
+ } else
+ p->ourip = __ourip;
+
+ p->branch = ast_random();
+ make_our_tag(p->tag, sizeof(p->tag));
+ p->ocseq = INITIAL_CSEQ;
+
+ if (useglobal_nat && sin) {
+ ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT);
+ p->recv = *sin;
+ do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE);
+ }
+
+ ast_string_field_set(p, fromdomain, default_fromdomain);
+ build_via(p);
+ ast_string_field_set(p, callid, callid);
+
+ /* Use this temporary pvt structure to send the message */
+ __transmit_response(p, msg, req, XMIT_UNRELIABLE);
+
+ /* Now do a simple destruction */
+ ast_string_field_free_all(p);
+
+ return 0;
+}
+
/*! \brief Transmit response, no retransmits */
static int transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req)
{