From e0883154cffeec8d6b73c01c34c81a94cc5f05a6 Mon Sep 17 00:00:00 2001 From: Mark Michelson Date: Mon, 25 Jun 2012 19:26:31 +0000 Subject: Re-fix how local tag is generated when sending a 481 to an INVITE. Match our local tag to whatever to-tag was sent in the initial INVITE. Because the size of the to-tag may not fit in the buffer in the sip_pvt, it has been changed to a string field. (closes issue ASTERISK-19892) reported by Walter Doekes Review: https://reviewboard.asterisk.org/r/1977 ........ Merged revisions 369352 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 369353 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@369367 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'channels/chan_sip.c') diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 94154dc3b..5efbfbf34 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1557,7 +1557,7 @@ static char *generate_random_string(char *buf, size_t size); static void build_callid_pvt(struct sip_pvt *pvt); static void change_callid_pvt(struct sip_pvt *pvt, const char *callid); static void build_callid_registry(struct sip_registry *reg, const struct ast_sockaddr *ourip, const char *fromdomain); -static void make_our_tag(char *tagbuf, size_t len); +static void make_our_tag(struct sip_pvt *pvt); static int add_header(struct sip_request *req, const char *var, const char *value); static int add_header_max_forwards(struct sip_pvt *dialog, struct sip_request *req); static int add_content(struct sip_request *req, const char *line); @@ -7855,9 +7855,9 @@ static void build_callid_registry(struct sip_registry *reg, const struct ast_soc } /*! \brief Make our SIP dialog tag */ -static void make_our_tag(char *tagbuf, size_t len) +static void make_our_tag(struct sip_pvt *pvt) { - snprintf(tagbuf, len, "as%08lx", ast_random()); + ast_string_field_build(pvt, tag, "as%08lx", ast_random()); } /*! \brief Allocate Session-Timers struct w/in dialog */ @@ -7999,7 +7999,7 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr, p->do_history = recordhistory; p->branch = ast_random(); - make_our_tag(p->tag, sizeof(p->tag)); + make_our_tag(p); p->ocseq = INITIAL_CSEQ; p->allowed_methods = UINT_MAX; @@ -8294,7 +8294,7 @@ static void forked_invite_init(struct sip_request *req, const char *new_theirtag memcpy(&p->flags, &original->flags, sizeof(p->flags)); copy_request(&p->initreq, &original->initreq); ast_string_field_set(p, theirtag, new_theirtag); - ast_copy_string(p->tag, original->tag, sizeof(p->tag)); + ast_string_field_set(p, tag, original->tag); ast_string_field_set(p, uri, original->uri); ast_string_field_set(p, our_contact, original->our_contact); ast_string_field_set(p, fullcontact, original->fullcontact); @@ -11103,7 +11103,7 @@ static int transmit_response_using_temp(ast_string_field callid, struct ast_sock } p->branch = ast_random(); - make_our_tag(p->tag, sizeof(p->tag)); + make_our_tag(p); p->ocseq = INITIAL_CSEQ; if (useglobal_nat && addr) { @@ -13970,7 +13970,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * return 0; } else { p = dialog_ref(r->call, "getting a copy of the r->call dialog in transmit_register"); - make_our_tag(p->tag, sizeof(p->tag)); /* create a new local tag for every register attempt */ + make_our_tag(p); /* create a new local tag for every register attempt */ ast_string_field_set(p, theirtag, NULL); /* forget their old tag, so we don't match tags when getting response */ } } else { @@ -23929,7 +23929,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int ast_string_field_set(p, exten, "s"); /* Initialize our tag */ - make_our_tag(p->tag, sizeof(p->tag)); + make_our_tag(p); /* First invitation - create the channel. Allocation * failures are handled below. */ @@ -26119,7 +26119,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, /* Initialize tag for new subscriptions */ if (ast_strlen_zero(p->tag)) - make_our_tag(p->tag, sizeof(p->tag)); + make_our_tag(p); if (!strncmp(eventheader, "presence", MAX(event_len, 8)) || !strncmp(eventheader, "dialog", MAX(event_len, 6))) { /* Presence, RFC 3842 */ unsigned int pidf_xml; @@ -26627,14 +26627,15 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct as if (!p->initreq.headers && req->has_to_tag) { /* If this is a first request and it got a to-tag, it is not for us */ if (!req->ignore && req->method == SIP_INVITE) { - /* We will be subversive here. By blanking out the to-tag of the request, - * it will cause us to attach our own generated to-tag instead. This way, - * when we receive an ACK, the ACK will contain the to-tag we generated, - * resulting in a proper to-tag match. + /* Just because we think this is a dialog-starting INVITE with a to-tag + * doesn't mean it actually is. It could be a reinvite for an established, but + * unknown dialog. In such a case, we need to change our tag to the + * incoming INVITE's to-tag so that they will recognize the 481 we send and + * so that we will properly match their incoming ACK. */ - char *to_header = (char *) sip_get_header(req, "To"); - char *tag = strstr(to_header, ";tag="); - *tag = '\0'; + char totag[128]; + gettag(req, "To", totag, sizeof(totag)); + ast_string_field_set(p, tag, totag); p->pendinginvite = p->icseq; transmit_response_reliable(p, "481 Call/Transaction Does Not Exist", req); /* Will cease to exist after ACK */ -- cgit v1.2.3