![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
sip3_parse.c File Reference
Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes)
Definition in file sip3_parse.c.
#include "asterisk.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <regex.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/udptl.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/musiconhold.h"
#include "asterisk/features.h"
#include "asterisk/causes.h"
#include "asterisk/utils.h"
#include "asterisk/file.h"
#include "asterisk/astobj.h"
#include "asterisk/linkedlists.h"
#include "asterisk/stringfields.h"
#include "asterisk/monitor.h"
#include "asterisk/compiler.h"
#include "sip3.h"
#include "sip3funcs.h"
Include dependency graph for sip3_parse.c:

Go to the source code of this file.
Functions | |
| const char * | __get_header (struct sip_request *req, const char *name, int *start) |
| int | copy_all_header (struct sip_request *req, struct sip_request *orig, const char *field) |
| Copy all headers from one request to another. | |
| int | copy_header (struct sip_request *req, struct sip_request *orig, const char *field) |
| Copy one header field from one request to another. | |
| void | copy_request (struct sip_request *dst, const struct sip_request *src) |
| copy SIP request (mostly used to save request for responses) | |
| int | copy_via_headers (struct sip_dialog *p, struct sip_request *req, struct sip_request *orig, const char *field) |
| Copy SIP VIA Headers from the request to the response. | |
| int | determine_firstline_parts (struct sip_request *req) |
| Parse first line of incoming SIP request. | |
| void | extract_uri (struct sip_dialog *p, struct sip_request *req) |
| Check Contact: URI of SIP message. | |
| const char * | find_alias (const char *name, const char *_default) |
| Find compressed SIP alias Structure for conversion between compressed SIP and "normal" SIP. | |
| static const char * | find_closing_quote (const char *start, const char *lim) |
| Locate closing quote in a string, skipping escaped quotes. optionally with a limit on the search. start must be past the first quote. | |
| int | find_sip_method (const char *msg) |
| find_sip_method: Find SIP method from header | |
| char * | generate_random_string (char *buf, size_t size) |
| Generate 32 byte random string for callid's etc. | |
| int | get_destination (struct sip_dialog *p, struct sip_request *oreq) |
| Find out who the call is for We use the INVITE request uri to find out Runs a dialplan lookup. | |
| const char * | get_header (struct sip_request *req, const char *name) |
| Get header from SIP request. | |
| char * | get_in_brackets (char *tmp) |
| Pick out text in brackets from character string. | |
| int | get_rdnis (struct sip_dialog *p, struct sip_request *oreq) |
| Get referring dnis. | |
| const char * | gettag (const char *header, char *tagbuf, int tagbufsize) |
| Get tag from packet. | |
| GNURK int | lws2sws (char *msgbuf, int len) |
| Parse multiline SIP headers into one header This is enabled if pedanticsipchecking is enabled. | |
| int | method_match (enum sipmethod id, const char *name) |
| returns true if 'name' (with optional trailing whitespace) matches the sip method 'id'. Strictly speaking, SIP methods are case SENSITIVE, but we do a case-insensitive comparison to be more tolerant. following Jon Postel's rule: Be gentle in what you accept, strict with what you send | |
| void | parse_moved_contact (struct sip_dialog *p, struct sip_request *req) |
| Parse 302 Moved temporalily response. | |
| GNURK void | parse_request (struct sip_request *req) |
| Parse a SIP message. | |
| unsigned int | parse_sip_options (struct sip_dialog *pvt, const char *supported) |
| Parse supported header in incoming packet. | |
| char * | sip_method2txt (int method) |
| return text string for sip method | |
| int | sip_method_needrtp (int method) |
| Check whether method needs RTP. | |
| char * | sip_option2text (int option) |
| Return text representation of SIP option. | |
| int | sip_option_lookup (const char *optionlabel) |
| Check if sip option is known to us, avoid x- options (non-standard). | |
| void | sip_options_print (int options, int fd) |
| Print options to cli. | |
| static void | sip_set_redirstr (struct sip_dialog *p, char *reason) |
| Translate referring cause. | |
Variables | |
| const struct cfsip_methods | sip_methods [] |
| static const struct cfsip_options | sip_options [] |
| List of well-known SIP options. If we get this in a require, we should check the list and answer accordingly. | |
|
||||||||||||||||
|
Definition at line 587 of file sip3_parse.c. References ast_log(), ast_test_flag, sip_request::header, sip_request::headers, len, LOG_ERROR, parse_request(), SIP_PKT_CONNECTED, and SIP_PKT_PARSED. 00588 { 00589 int pass; 00590 00591 if (!ast_test_flag(req, SIP_PKT_PARSED)) { 00592 /* Ok, so this req is not parse by parse_request yet. */ 00593 /* Parsing it before we have finished re-transmit may be bad. */ 00594 if (!ast_test_flag(req, SIP_PKT_CONNECTED)) 00595 parse_request(req); 00596 else { 00597 ast_log(LOG_ERROR, "Can't get header %s from request before parsing. Hang in for a jumpy ride!\n", name); 00598 return ""; 00599 } 00600 00601 } 00602 /* 00603 * Technically you can place arbitrary whitespace both before and after the ':' in 00604 * a header, although RFC3261 clearly says you shouldn't before, and place just 00605 * one afterwards. If you shouldn't do it, what absolute idiot decided it was 00606 * a good idea to say you can do it, and if you can do it, why in the hell would. 00607 * you say you shouldn't. 00608 */ 00609 for (pass = 0; name && pass < 2;pass++) { 00610 int x, len = strlen(name); 00611 for (x=*start; x<req->headers; x++) { 00612 if (!strncasecmp(req->header[x], name, len)) { 00613 char *r = req->header[x] + len; /* skip name */ 00614 r = ast_skip_blanks(r); 00615 00616 if (*r == ':') { 00617 *start = x+1; 00618 return ast_skip_blanks(r+1); 00619 } 00620 } 00621 } 00622 if (pass == 0) /* Try aliases */ 00623 name = find_alias(name, NULL); 00624 } 00625 00626 /* Don't return NULL, so get_header is always a valid pointer */ 00627 return ""; 00628 }
|
|
||||||||||||||||
|
Copy all headers from one request to another.
Definition at line 649 of file sip3_parse.c. References __get_header(), add_header(), and ast_strlen_zero(). 00650 { 00651 int start = 0; 00652 int copied = 0; 00653 int res; 00654 00655 for (;;) { 00656 const char *tmp = __get_header(orig, field, &start); 00657 00658 if (ast_strlen_zero(tmp)) 00659 break; 00660 /* Add what we're responding to */ 00661 res = add_header(req, field, tmp); 00662 if (res != -1) 00663 copied++; 00664 else 00665 return -1; 00666 00667 } 00668 return copied ? 0 : -1; 00669 }
|
|
||||||||||||||||
|
Copy one header field from one request to another.
Definition at line 638 of file sip3_parse.c. References add_header(), ast_log(), ast_strlen_zero(), get_header(), and LOG_NOTICE. 00639 { 00640 const char *tmp = get_header(orig, field); 00641 00642 if (!ast_strlen_zero(tmp)) /* Add what we're responding to */ 00643 return add_header(req, field, tmp); 00644 ast_log(LOG_NOTICE, "No field '%s' present to copy\n", field); 00645 return -1; 00646 }
|
|
||||||||||||
|
copy SIP request (mostly used to save request for responses)
Definition at line 238 of file sip3_parse.c. References ast_calloc, ast_log(), free, LOG_DEBUG, offset, and option_debug. 00239 { 00240 long offset; 00241 int x; 00242 00243 offset = ((void *)dst) - ((void *)src); 00244 /* First copy stuff */ 00245 memcpy(dst, src, sizeof(*dst)); 00246 00247 /* Now, fix data part */ 00248 if (dst->data) 00249 free(dst->data); 00250 dst->data = ast_calloc(1, src->data_size); 00251 dst->data_size = src->data_size; 00252 memcpy(dst->data, src->data, src->data_size); 00253 00254 /* Now fix pointer arithmetic */ 00255 for (x=0; x < src->headers; x++) 00256 dst->header[x] += offset; 00257 for (x=0; x < src->lines; x++) 00258 dst->line[x] += offset; 00259 00260 if (option_debug > 3) 00261 ast_log(LOG_DEBUG, "==== Copied request... \n"); 00262 }
|
|
||||||||||||||||||||
|
Copy SIP VIA Headers from the request to the response.
Definition at line 677 of file sip3_parse.c. References __get_header(), add_header(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, sip_dialog::flags, sip_dialog::recv, SIP_NAT, SIP_NAT_ALWAYS, and SIP_NAT_RFC3581. 00678 { 00679 int copied = 0; 00680 int start = 0; 00681 00682 for (;;) { 00683 char new[256]; 00684 const char *oh = __get_header(orig, field, &start); 00685 00686 if (ast_strlen_zero(oh)) 00687 break; 00688 00689 if (!copied) { /* Only check for empty rport in topmost via header */ 00690 char leftmost[256], *others, *rport; 00691 00692 /* Only work on leftmost value */ 00693 ast_copy_string(leftmost, oh, sizeof(leftmost)); 00694 others = strchr(leftmost, ','); 00695 if (others) 00696 *others++ = '\0'; 00697 00698 /* Find ;rport; (empty request) */ 00699 rport = strstr(leftmost, ";rport"); 00700 if (rport && *(rport+6) == '=') 00701 rport = NULL; /* We already have a parameter to rport */ 00702 00703 if (rport && ( (ast_test_flag(&p->flags[0], SIP_NAT) == SIP_NAT_ALWAYS) || 00704 (ast_test_flag(&p->flags[0], SIP_NAT) == SIP_NAT_RFC3581) ) ) { 00705 /* We need to add received port - rport */ 00706 char *end; 00707 00708 rport = strstr(leftmost, ";rport"); 00709 00710 if (rport) { 00711 end = strchr(rport + 1, ';'); 00712 if (end) 00713 memmove(rport, end, strlen(end) + 1); 00714 else 00715 *rport = '\0'; 00716 } 00717 00718 /* Add rport to first VIA header if requested */ 00719 /* Whoo hoo! Now we can indicate port address translation too! Just 00720 another RFC (RFC3581). I'll leave the original comments in for 00721 posterity. */ 00722 snprintf(new, sizeof(new), "%s;received=%s;rport=%d%s%s", 00723 leftmost, ast_inet_ntoa(p->recv.sin_addr), 00724 ntohs(p->recv.sin_port), 00725 others ? "," : "", others ? others : ""); 00726 } else { 00727 /* We should *always* add a received to the topmost via */ 00728 snprintf(new, sizeof(new), "%s;received=%s%s%s", 00729 leftmost, ast_inet_ntoa(p->recv.sin_addr), 00730 others ? "," : "", others ? others : ""); 00731 00732 } 00733 oh = new; /* the header to copy */ 00734 } /* else add the following via headers untouched */ 00735 add_header(req, field, oh); 00736 copied++; 00737 } 00738 if (!copied) { 00739 ast_log(LOG_NOTICE, "No header field '%s' present to copy\n", field); 00740 return -1; 00741 } 00742 return 0; 00743 }
|
|
|
Parse first line of incoming SIP request.
Definition at line 865 of file sip3_parse.c. References ast_log(), sip_request::header, LOG_WARNING, sip_request::rlPart1, and sip_request::rlPart2. 00866 { 00867 char *e = ast_skip_blanks(req->header[0]); /* there shouldn't be any */ 00868 00869 if (!*e) 00870 return -1; 00871 req->rlPart1 = e; /* method or protocol */ 00872 e = ast_skip_nonblanks(e); 00873 if (*e) 00874 *e++ = '\0'; 00875 /* Get URI or status code */ 00876 e = ast_skip_blanks(e); 00877 if ( !*e ) 00878 return -1; 00879 ast_trim_blanks(e); 00880 00881 if (!strcasecmp(req->rlPart1, "SIP/2.0") ) { /* We have a response */ 00882 if (strlen(e) < 3) /* status code is 3 digits */ 00883 return -1; 00884 req->rlPart2 = e; 00885 } else { /* We have a request */ 00886 if ( *e == '<' ) { /* XXX the spec says it must not be in <> ! */ 00887 ast_log(LOG_WARNING, "bogus uri in <> %s\n", e); 00888 e++; 00889 if (!*e) 00890 return -1; 00891 } 00892 req->rlPart2 = e; /* URI */ 00893 e = ast_skip_nonblanks(e); 00894 if (*e) 00895 *e++ = '\0'; 00896 e = ast_skip_blanks(e); 00897 if (strcasecmp(e, "SIP/2.0") ) { 00898 ast_log(LOG_WARNING, "Bad request protocol %s\n", e); 00899 return -1; 00900 } 00901 } 00902 return 1; 00903 }
|
|
||||||||||||
|
Check Contact: URI of SIP message.
Definition at line 906 of file sip3_parse.c. References ast_string_field_set, ast_strlen_zero(), get_header(), get_in_brackets(), and strsep(). 00907 { 00908 char stripped[256]; 00909 char *c; 00910 00911 ast_copy_string(stripped, get_header(req, "Contact"), sizeof(stripped)); 00912 c = get_in_brackets(stripped); 00913 c = strsep(&c, ";"); /* trim ; and beyond */ 00914 if (!ast_strlen_zero(c)) 00915 ast_string_field_set(p, uri, c); 00916 }
|
|
||||||||||||
|
Find compressed SIP alias Structure for conversion between compressed SIP and "normal" SIP.
Definition at line 320 of file sip3_parse.c. References aliases. 00321 { 00322 /*! \brief Structure for conversion between compressed SIP and "normal" SIP */ 00323 static const struct cfalias { 00324 char * const fullname; 00325 char * const shortname; 00326 } aliases[] = { 00327 { "Content-Type", "c" }, 00328 { "Content-Encoding", "e" }, 00329 { "From", "f" }, 00330 { "Call-ID", "i" }, 00331 { "Contact", "m" }, 00332 { "Content-Length", "l" }, 00333 { "Subject", "s" }, 00334 { "To", "t" }, 00335 { "Supported", "k" }, 00336 { "Refer-To", "r" }, 00337 { "Referred-By", "b" }, 00338 { "Allow-Events", "u" }, 00339 { "Event", "o" }, 00340 { "Via", "v" }, 00341 { "Accept-Contact", "a" }, 00342 { "Reject-Contact", "j" }, 00343 { "Request-Disposition", "d" }, 00344 { "Session-Expires", "x" }, 00345 { "Identity", "y" }, 00346 { "Identity-Info", "n" }, 00347 }; 00348 int x; 00349 00350 for (x=0; x<sizeof(aliases) / sizeof(aliases[0]); x++) 00351 if (!strcasecmp(aliases[x].fullname, name)) 00352 return aliases[x].shortname; 00353 00354 return _default; 00355 }
|
|
||||||||||||
|
Locate closing quote in a string, skipping escaped quotes. optionally with a limit on the search. start must be past the first quote.
Definition at line 749 of file sip3_parse.c. References s. 00750 { 00751 char last_char = '\0'; 00752 const char *s; 00753 for (s = start; *s && s != lim; last_char = *s++) { 00754 if (*s == '"' && last_char != '\\') 00755 break; 00756 } 00757 return s; 00758 }
|
|
|
find_sip_method: Find SIP method from header
Definition at line 163 of file sip3_parse.c. References ast_strlen_zero(), method_match(), and sip_methods. 00164 { 00165 int i, res = 0; 00166 00167 if (ast_strlen_zero(msg)) 00168 return 0; 00169 for (i = 1; i < (sizeof(sip_methods) / sizeof(sip_methods[0])) && !res; i++) { 00170 if (method_match(i, msg)) 00171 res = sip_methods[i].id; 00172 } 00173 return res; 00174 }
|
|
||||||||||||
|
Generate 32 byte random string for callid's etc.
Definition at line 852 of file sip3_parse.c. References ast_random(). 00853 { 00854 long val[4]; 00855 int x; 00856 00857 for (x=0; x<4; x++) 00858 val[x] = ast_random(); 00859 snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]); 00860 00861 return buf; 00862 }
|
|
||||||||||||
|
Find out who the call is for We use the INVITE request uri to find out Runs a dialplan lookup.
Definition at line 448 of file sip3_parse.c. References sip_globals::allow_external_domains, ast_log(), AST_MAX_EXTENSION, ast_string_field_set, ast_strlen_zero(), ast_uri_decode(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, check_sip_domain(), context, domains_configured(), FALSE, sip_request::from, get_header(), get_in_brackets(), global, sip_dialog::initreq, LOG_DEBUG, LOG_WARNING, sip_request::method, option_debug, REG_MAGICMARKER, sip_dialog::registry, regl, sip_request::rlPart2, SIP_INVITE, sip_method2txt(), SIP_REFER, strsep(), and TRUE. 00449 { 00450 char tmp[256] = "", *uri, *a; 00451 char tmpf[256] = "", *from; 00452 struct sip_request *req; 00453 char *colon; 00454 int localdomain = TRUE; 00455 00456 req = oreq; 00457 if (!req) 00458 req = p->initreq; 00459 00460 /* Find the request URI */ 00461 if (req->rlPart2) 00462 ast_copy_string(tmp, req->rlPart2, sizeof(tmp)); 00463 00464 ast_uri_decode(tmp); 00465 00466 uri = get_in_brackets(tmp); 00467 00468 if (strncmp(uri, "sip:", 4)) { 00469 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", uri); 00470 return -1; 00471 } 00472 uri += 4; 00473 00474 /* Now find the From: caller ID and name */ 00475 ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf)); 00476 if (!ast_strlen_zero(tmpf)) { 00477 ast_uri_decode(tmpf); 00478 from = get_in_brackets(tmpf); 00479 } else { 00480 from = NULL; 00481 } 00482 00483 if (!ast_strlen_zero(from)) { 00484 if (strncmp(from, "sip:", 4)) { 00485 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", from); 00486 return -1; 00487 } 00488 from += 4; 00489 if ((a = strchr(from, '@'))) 00490 *a++ = '\0'; 00491 else 00492 a = from; /* just a domain */ 00493 from = strsep(&from, ";"); /* Remove userinfo options */ 00494 a = strsep(&a, ";"); /* Remove URI options */ 00495 ast_string_field_set(p, fromdomain, a); 00496 } 00497 00498 /* Skip any options and find the domain */ 00499 00500 /* Get the target domain */ 00501 if ((a = strchr(uri, '@'))) { 00502 *a++ = '\0'; 00503 } else { /* No username part */ 00504 a = uri; 00505 uri = "s"; /* Set extension to "s" */ 00506 } 00507 colon = strchr(a, ':'); /* Remove :port */ 00508 if (colon) 00509 *colon = '\0'; 00510 00511 uri = strsep(&uri, ";"); /* Remove userinfo options */ 00512 a = strsep(&a, ";"); /* Remove URI options */ 00513 00514 ast_string_field_set(p, domain, a); 00515 00516 if (domains_configured()) { 00517 char domain_context[AST_MAX_EXTENSION]; 00518 00519 domain_context[0] = '\0'; 00520 if (!check_sip_domain(p->domain, domain_context, sizeof(domain_context))) { 00521 localdomain = FALSE; 00522 if (!global.allow_external_domains && (req->method == SIP_INVITE || req->method == SIP_REFER)) { 00523 if (option_debug) 00524 ast_log(LOG_DEBUG, "Got SIP %s to non-local domain '%s'; refusing request.\n", sip_method2txt(req->method), p->domain); 00525 return -2; 00526 } 00527 } 00528 /* If we have a domain context defined, overwrite the original context */ 00529 if (!ast_strlen_zero(domain_context)) 00530 ast_string_field_set(p, context, domain_context); 00531 } 00532 00533 /* If the URI starts with our magic marker and has a corresponding 00534 entry in the registry, then replace the URI with the extension 00535 we want to use */ 00536 /* We don't have to check this at all if we have no registry entries... */ 00537 if (localdomain && req->method == SIP_INVITE) { 00538 if (option_debug) 00539 ast_log(LOG_DEBUG, "Checking %s for magic registry marker \n", uri); 00540 /* Check if the incoming URI is a registry entry */ 00541 /* Need a function in ASTOBJ to check if there are objects 00542 in the container at all here to avoid this check 00543 when we have no registry entries */ 00544 if (!strncmp(uri, REG_MAGICMARKER, strlen(REG_MAGICMARKER))) { 00545 int found = FALSE; 00546 00547 if (option_debug) 00548 ast_log(LOG_DEBUG, "Checking for %s in registry\n", uri); 00549 /* Traverse the registry to find something */ 00550 ASTOBJ_CONTAINER_TRAVERSE(®l, !found, do { 00551 ASTOBJ_RDLOCK(iterator); 00552 if (!strcmp(uri, iterator->contact)) { 00553 found = TRUE; 00554 /* Use the extension of this registry item for the incoming call */ 00555 uri = (char *) iterator->extension; 00556 p->registry = iterator; 00557 } 00558 ASTOBJ_UNLOCK(iterator); 00559 } while(0)); 00560 } 00561 } 00562 00563 00564 if (sip_debug_test_pvt(p)) 00565 ast_verbose("Looking for %s in %s (domain %s)\n", uri, p->context, p->domain); 00566 00567 /* Check the dialplan for the username part of the request URI, 00568 the domain will be stored in the SIPDOMAIN variable 00569 Return 0 if we have a matching extension */ 00570 if (ast_exists_extension(NULL, p->context, uri, 1, from) || 00571 !strcmp(uri, ast_pickup_ext())) { 00572 if (!oreq) 00573 ast_string_field_set(p, exten, uri); 00574 return 0; 00575 } 00576 00577 /* Return 1 for pickup extension or overlap dialling support (if we support it) */ 00578 if((ast_test_flag(&global.flags[1], SIP_PAGE2_ALLOWOVERLAP) && 00579 ast_canmatch_extension(NULL, p->context, uri, 1, from)) || 00580 !strncmp(uri, ast_pickup_ext(), strlen(uri))) { 00581 return 1; 00582 } 00583 00584 return -1; 00585 }
|
|
||||||||||||
|
Get header from SIP request.
Definition at line 631 of file sip3_parse.c. References __get_header(). 00632 { 00633 int start = 0; 00634 return __get_header(req, name, &start); 00635 }
|
|
|
Pick out text in brackets from character string.
Definition at line 771 of file sip3_parse.c. References ast_log(), find_closing_quote(), LOG_WARNING, and parse(). 00772 { 00773 const char *parse = tmp; 00774 char *first_bracket; 00775 00776 /* 00777 * Skip any quoted text until we find the part in brackets. 00778 * On any error give up and return the full string. 00779 */ 00780 while ( (first_bracket = strchr(parse, '<')) ) { 00781 char *first_quote = strchr(parse, '"'); 00782 00783 if (!first_quote || first_quote > first_bracket) 00784 break; /* no need to look at quoted part */ 00785 /* the bracket is within quotes, so ignore it */ 00786 parse = find_closing_quote(first_quote + 1, NULL); 00787 if (!*parse) { /* not found, return full string ? */ 00788 /* XXX or be robust and return in-bracket part ? */ 00789 ast_log(LOG_WARNING, "No closing quote found in '%s'\n", tmp); 00790 break; 00791 } 00792 parse++; 00793 } 00794 if (first_bracket) { 00795 char *second_bracket = strchr(first_bracket + 1, '>'); 00796 if (second_bracket) { 00797 *second_bracket = '\0'; 00798 tmp = first_bracket + 1; 00799 } else { 00800 ast_log(LOG_WARNING, "No closing bracket found in '%s'\n", tmp); 00801 } 00802 } 00803 return tmp; 00804 }
|
|
||||||||||||
|
Get referring dnis.
Definition at line 390 of file sip3_parse.c. References ast_log(), ast_string_field_set, ast_strip_quoted(), ast_strlen_zero(), ast_verbose(), exten, get_header(), get_in_brackets(), sip_dialog::initreq, LOG_WARNING, sip_dialog::owner, pbx_builtin_setvar_helper(), sip_debug_test_pvt(), sip_set_redirstr(), strcasestr(), and strsep(). 00391 { 00392 char tmp[256], *exten, *rexten, *rdomain; 00393 char *params, *reason = NULL; 00394 struct sip_request *req; 00395 00396 req = oreq ? oreq : p->initreq; 00397 00398 ast_copy_string(tmp, get_header(req, "Diversion"), sizeof(tmp)); 00399 if (ast_strlen_zero(tmp)) 00400 return 0; 00401 00402 exten = get_in_brackets(tmp); 00403 if (strncmp(exten, "sip:", 4)) { 00404 ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", exten); 00405 return -1; 00406 } 00407 exten += 4; 00408 00409 /* Get diversion-reason param if present */ 00410 if ((params = strchr(tmp, ';'))) { 00411 *params = '\0'; /* Cut off parameters */ 00412 params++; 00413 while (*params == ';' || *params == ' ') 00414 params++; 00415 /* Check if we have a reason parameter */ 00416 if ((reason = strcasestr(params, "reason="))) { 00417 reason+=7; 00418 /* Remove enclosing double-quotes */ 00419 if (*reason == '"') 00420 ast_strip_quoted(reason, "\"", "\""); 00421 if (!ast_strlen_zero(reason)) { 00422 sip_set_redirstr(p, reason); 00423 if (p->owner) { 00424 pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause); 00425 pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason); 00426 } 00427 } 00428 } 00429 } 00430 00431 rdomain = exten; 00432 rexten = strsep(&rdomain, "@"); /* trim anything after @ */ 00433 if (p->owner) 00434 pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain); 00435 00436 if (sip_debug_test_pvt(p)) 00437 ast_verbose("RDNIS for this call is is %s (reason %s)\n", exten, reason ? reason : ""); 00438 00439 ast_string_field_set(p, rdnis, rexten); 00440 00441 return 0; 00442 }
|
|
||||||||||||||||
|
Get tag from packet.
Definition at line 200 of file sip3_parse.c. References strcasestr(), and strsep(). 00201 { 00202 const char *thetag; 00203 00204 if (!tagbuf) 00205 return NULL; 00206 tagbuf[0] = '\0'; /* reset the buffer */ 00207 thetag = strcasestr(header, ";tag="); 00208 if (thetag) { 00209 thetag += 5; 00210 ast_copy_string(tagbuf, thetag, tagbufsize); 00211 return strsep(&tagbuf, ";"); 00212 } 00213 return NULL; 00214 }
|
|
||||||||||||
|
Parse multiline SIP headers into one header This is enabled if pedanticsipchecking is enabled. Definition at line 807 of file sip3_parse.c. 00808 { 00809 int h = 0, t = 0; 00810 int lws = 0; 00811 00812 for (; h < len;) { 00813 /* Eliminate all CRs */ 00814 if (msgbuf[h] == '\r') { 00815 h++; 00816 continue; 00817 } 00818 /* Check for end-of-line */ 00819 if (msgbuf[h] == '\n') { 00820 /* Check for end-of-message */ 00821 if (h + 1 == len) 00822 break; 00823 /* Check for a continuation line */ 00824 if (msgbuf[h + 1] == ' ' || msgbuf[h + 1] == '\t') { 00825 /* Merge continuation line */ 00826 h++; 00827 continue; 00828 } 00829 /* Propagate LF and start new line */ 00830 msgbuf[t++] = msgbuf[h++]; 00831 lws = 0; 00832 continue; 00833 } 00834 if (msgbuf[h] == ' ' || msgbuf[h] == '\t') { 00835 if (lws) { 00836 h++; 00837 continue; 00838 } 00839 msgbuf[t++] = msgbuf[h++]; 00840 lws = 1; 00841 continue; 00842 } 00843 msgbuf[t++] = msgbuf[h++]; 00844 if (lws) 00845 lws = 0; 00846 } 00847 msgbuf[t] = '\0'; 00848 return t; 00849 }
|
|
||||||||||||
|
returns true if 'name' (with optional trailing whitespace) matches the sip method 'id'. Strictly speaking, SIP methods are case SENSITIVE, but we do a case-insensitive comparison to be more tolerant. following Jon Postel's rule: Be gentle in what you accept, strict with what you send
Definition at line 152 of file sip3_parse.c. References len, sip_methods, and cfsip_options::text. 00153 { 00154 int len = strlen(sip_methods[id].text); 00155 int l_name = name ? strlen(name) : 0; 00156 00157 /* true if the string is long enough, and ends with whitespace, and matches */ 00158 return (l_name >= len && name[len] < 33 && 00159 !strncasecmp(sip_methods[id].text, name, len)); 00160 }
|
|
||||||||||||
|
Parse 302 Moved temporalily response.
Definition at line 919 of file sip3_parse.c. References ast_log(), ast_string_field_build, ast_string_field_set, ast_test_flag, sip_dialog::flags, get_header(), get_in_brackets(), LOG_DEBUG, option_debug, sip_dialog::owner, pbx_builtin_setvar_helper(), s, SIP_PROMISCREDIR, and strsep(). 00920 { 00921 char tmp[256]; 00922 char *s, *e; 00923 char *domain; 00924 00925 ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp)); 00926 s = get_in_brackets(tmp); 00927 s = strsep(&s, ";"); /* strip ; and beyond */ 00928 if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) { 00929 if (!strncasecmp(s, "sip:", 4)) 00930 s += 4; 00931 e = strchr(s, '/'); 00932 if (e) 00933 *e = '\0'; 00934 if (option_debug) 00935 ast_log(LOG_DEBUG, "Found promiscuous redirection to 'SIP/%s'\n", s); 00936 if (p->owner) 00937 ast_string_field_build(p->owner, call_forward, "SIP/%s", s); 00938 } else { 00939 e = strchr(tmp, '@'); 00940 if (e) { 00941 *e++ = '\0'; 00942 domain = e; 00943 } else { 00944 /* No username part */ 00945 domain = tmp; 00946 } 00947 e = strchr(tmp, '/'); 00948 if (e) 00949 *e = '\0'; 00950 if (!strncasecmp(s, "sip:", 4)) 00951 s += 4; 00952 if (option_debug > 1) 00953 ast_log(LOG_DEBUG, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain); 00954 if (p->owner) { 00955 pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain); 00956 ast_string_field_set(p->owner, call_forward, s); 00957 } 00958 } 00959 }
|
|
|
Parse a SIP message.
Definition at line 964 of file sip3_parse.c. References ast_log(), ast_strlen_zero(), sip_request::data, sip_request::header, sip_request::headers, sip_request::line, LOG_DEBUG, option_debug, sip_request::seqno, SIP_MAX_HEADERS, SIP_MAX_LINES, and sipdebug. 00965 { 00966 char *c = req->data, **dst = req->header; 00967 int i = 0, lim = SIP_MAX_HEADERS - 1; 00968 int seqno = 0; 00969 00970 req->header[0] = c; 00971 req->headers = -1; /* mark that we are working on the header */ 00972 for (; *c; c++) { 00973 if (*c == '\r') /* remove \r */ 00974 *c = '\0'; 00975 else if (*c == '\n') { /* end of this line */ 00976 *c = '\0'; 00977 if (sipdebug && option_debug > 3) 00978 ast_log(LOG_DEBUG, "%7s %2d [%3d]: %s\n", 00979 req->headers < 0 ? "Header" : "Body", 00980 i, (int)strlen(dst[i]), dst[i]); 00981 if (ast_strlen_zero(dst[i]) && req->headers < 0) { 00982 req->headers = i; /* record number of header lines */ 00983 dst = req->line; /* start working on the body */ 00984 i = 0; 00985 lim = SIP_MAX_LINES - 1; 00986 } else { /* move to next line, check for overflows */ 00987 if (i++ >= lim) 00988 break; 00989 } 00990 dst[i] = c + 1; /* record start of next line */ 00991 } 00992 } 00993 /* update count of header or body lines */ 00994 if (req->headers >= 0) /* we are in the body */ 00995 req->lines = i; 00996 else { /* no body */ 00997 req->headers = i; 00998 req->lines = 0; 00999 req->line[0] = ""; 01000 } 01001 01002 if (*c) 01003 ast_log(LOG_WARNING, "Too many lines, skipping <%s>\n", c); 01004 /* Split up the first line parts */ 01005 determine_firstline_parts(req); 01006 /* Determine the seqno of this request once and for all */ 01007 01008 ast_set_flag(req, SIP_PKT_PARSED); 01009 01010 req->callid = get_header(req, "Call-ID"); 01011 req->from = get_header(req, "From"); 01012 req->to = get_header(req, "To"); 01013 req->via = get_header(req, "Via"); /* Get the first via header only */ 01014 req->cseqheader = get_header(req, "CSeq"); 01015 /* Seqno can be zero, but anyway... */ 01016 if (!req->seqno && sscanf(req->cseqheader, "%d ", &seqno) != 1) 01017 req->seqno = seqno; 01018 }
|
|
||||||||||||
|
Parse supported header in incoming packet.
Definition at line 266 of file sip3_parse.c. References ast_log(), ast_strdupa, ast_strlen_zero(), FALSE, cfsip_options::id, LOG_DEBUG, option_debug, sip_option_lookup(), sip_options, and sipdebug. 00267 { 00268 char *next, *sep; 00269 char *temp; 00270 unsigned int profile = 0; 00271 int i, found; 00272 00273 if (ast_strlen_zero(supported)) 00274 return 0; 00275 temp = ast_strdupa(supported); 00276 00277 if (option_debug > 2 && sipdebug) 00278 ast_log(LOG_DEBUG, "Begin: parsing SIP \"Supported: %s\"\n", supported); 00279 00280 for (next = temp; next; next = sep) { 00281 found = FALSE; 00282 if ( (sep = strchr(next, ',')) != NULL) 00283 *sep++ = '\0'; 00284 next = ast_skip_blanks(next); 00285 if (option_debug > 2 && sipdebug) 00286 ast_log(LOG_DEBUG, "Got SIP option: -%s-\n", next); 00287 i = sip_option_lookup(next); 00288 if (i > 0) 00289 profile |= sip_options[i].id; 00290 } 00291 00292 if (pvt) 00293 pvt->sipoptions = profile; 00294 return profile; 00295 }
|
|
|
return text string for sip method
Definition at line 177 of file sip3_parse.c. References ast_log(), LOG_DEBUG, option_debug, and sip_methods. Referenced by __sip_autodestruct(), __sip_destroy(), __sip_pretend_ack(), __sip_semi_ack(), append_send_history(), build_reply_digest(), do_proxy_auth(), get_destination(), handle_request(), handle_request_subscribe(), handle_response(), init_req(), reqprep(), retrans_pkt(), sip_alloc(), sip_scheddestroy(), transmit_final_response(), and transmit_register(). 00178 { 00179 int max = sizeof(sip_methods) / sizeof(sip_methods[0]); 00180 00181 if (method > max || method < 0) { 00182 if (option_debug > 3) 00183 ast_log(LOG_DEBUG, "Unknown SIP method %d given to this function. Strange... \n", method); 00184 return "<unknown>"; 00185 } 00186 return sip_methods[method].text; 00187 }
|
|
|
Check whether method needs RTP.
Definition at line 190 of file sip3_parse.c. References cfsip_methods::need_rtp, and sip_methods. Referenced by sip_alloc(). 00191 { 00192 return sip_methods[method].need_rtp; 00193 }
|
|
|
Return text representation of SIP option.
Definition at line 298 of file sip3_parse.c. References sip_options, and cfsip_options::text. 00299 { 00300 return sip_options[option].text; 00301 }
|
|
|
Check if sip option is known to us, avoid x- options (non-standard).
Definition at line 217 of file sip3_parse.c. References ast_log(), LOG_DEBUG, option_debug, sip_options, sipdebug, and cfsip_options::text. Referenced by parse_sip_options(). 00218 { 00219 int i; 00220 00221 for (i=0; i < (sizeof(sip_options) / sizeof(sip_options[0])); i++) { 00222 if (!strcasecmp(optionlabel, sip_options[i].text)) { 00223 if (option_debug > 2 && sipdebug) 00224 ast_log(LOG_DEBUG, "Matched SIP option: %s\n", optionlabel); 00225 return i; 00226 } 00227 } 00228 if (option_debug > 2) { 00229 if (!strncasecmp(optionlabel, "x-", 2)) 00230 ast_log(LOG_DEBUG, "Found private SIP option, not supported: %s\n", optionlabel); 00231 else 00232 ast_log(LOG_DEBUG, "Found no match for SIP option: %s (Please file bug report!)\n", optionlabel); 00233 } 00234 return -1; 00235 }
|
|
||||||||||||
|
Print options to cli.
Definition at line 304 of file sip3_parse.c. References ast_cli(), sip_options, and cfsip_options::text. Referenced by _sip_show_device(), and sip_show_channel(). 00305 { 00306 int x; 00307 int lastoption = -1; 00308 00309 for (x=0 ; (x < (sizeof(sip_options) / sizeof(sip_options[0]))); x++) { 00310 if (sip_options[x].id != lastoption) { 00311 if (options & sip_options[x].id) 00312 ast_cli(fd, "%s ", sip_options[x].text); 00313 lastoption = x; 00314 } 00315 } 00316 }
|
|
||||||||||||
|
Translate referring cause.
Definition at line 359 of file sip3_parse.c. References ast_string_field_set. 00359 { 00360 00361 if (strcmp(reason, "unknown")==0) { 00362 ast_string_field_set(p, redircause, "UNKNOWN"); 00363 } else if (strcmp(reason, "user-busy")==0) { 00364 ast_string_field_set(p, redircause, "BUSY"); 00365 } else if (strcmp(reason, "no-answer")==0) { 00366 ast_string_field_set(p, redircause, "NOANSWER"); 00367 } else if (strcmp(reason, "unavailable")==0) { 00368 ast_string_field_set(p, redircause, "UNREACHABLE"); 00369 } else if (strcmp(reason, "unconditional")==0) { 00370 ast_string_field_set(p, redircause, "UNCONDITIONAL"); 00371 } else if (strcmp(reason, "time-of-day")==0) { 00372 ast_string_field_set(p, redircause, "UNKNOWN"); 00373 } else if (strcmp(reason, "do-not-disturb")==0) { 00374 ast_string_field_set(p, redircause, "UNKNOWN"); 00375 } else if (strcmp(reason, "deflection")==0) { 00376 ast_string_field_set(p, redircause, "UNKNOWN"); 00377 } else if (strcmp(reason, "follow-me")==0) { 00378 ast_string_field_set(p, redircause, "UNKNOWN"); 00379 } else if (strcmp(reason, "out-of-service")==0) { 00380 ast_string_field_set(p, redircause, "UNREACHABLE"); 00381 } else if (strcmp(reason, "away")==0) { 00382 ast_string_field_set(p, redircause, "UNREACHABLE"); 00383 } else { 00384 ast_string_field_set(p, redircause, "UNKNOWN"); 00385 } 00386 }
|
|
|
XXX Note that sip_methods[i].id == i must hold or the code breaks Definition at line 86 of file sip3_parse.c. |
|
|
List of well-known SIP options. If we get this in a require, we should check the list and answer accordingly.
Definition at line 107 of file sip3_parse.c. |