![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
sip3_parse.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2007, Digium, Inc. 00005 * and Edvina AB, Sollentuna, Sweden (chan_sip3 changes/additions) 00006 * 00007 * Mark Spencer <markster@digium.com> 00008 * 00009 * See http://www.asterisk.org for more information about 00010 * the Asterisk project. Please do not directly contact 00011 * any of the maintainers of this project for assistance; 00012 * the project provides a web site, mailing lists and IRC 00013 * channels for your use. 00014 * 00015 * This program is free software, distributed under the terms of 00016 * the GNU General Public License Version 2. See the LICENSE file 00017 * at the top of the source tree. 00018 */ 00019 00020 /*! 00021 * \file 00022 * \brief Various SIP parsing functions 00023 * Version 3 of chan_sip 00024 * 00025 * \author Mark Spencer <markster@digium.com> 00026 * \author Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes) 00027 * 00028 * See Also: 00029 * \arg \ref AstCREDITS 00030 * 00031 */ 00032 00033 #include "asterisk.h" 00034 00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 53128 $") 00036 00037 #include <stdio.h> 00038 #include <ctype.h> 00039 #include <string.h> 00040 #include <unistd.h> 00041 #include <sys/socket.h> 00042 #include <sys/ioctl.h> 00043 #include <net/if.h> 00044 #include <errno.h> 00045 #include <stdlib.h> 00046 #include <fcntl.h> 00047 #include <netdb.h> 00048 #include <signal.h> 00049 #include <sys/signal.h> 00050 #include <netinet/in.h> 00051 #include <netinet/in_systm.h> 00052 #include <arpa/inet.h> 00053 #include <netinet/ip.h> 00054 #include <regex.h> 00055 00056 #include "asterisk/lock.h" 00057 #include "asterisk/channel.h" 00058 #include "asterisk/config.h" 00059 #include "asterisk/logger.h" 00060 #include "asterisk/module.h" 00061 #include "asterisk/pbx.h" 00062 #include "asterisk/options.h" 00063 #include "asterisk/sched.h" 00064 #include "asterisk/io.h" 00065 #include "asterisk/rtp.h" 00066 #include "asterisk/udptl.h" 00067 #include "asterisk/acl.h" 00068 #include "asterisk/manager.h" 00069 #include "asterisk/callerid.h" 00070 #include "asterisk/cli.h" 00071 #include "asterisk/musiconhold.h" 00072 #include "asterisk/features.h" 00073 #include "asterisk/causes.h" 00074 #include "asterisk/utils.h" 00075 #include "asterisk/file.h" 00076 #include "asterisk/astobj.h" 00077 #include "asterisk/linkedlists.h" 00078 #include "asterisk/stringfields.h" 00079 #include "asterisk/monitor.h" 00080 #include "asterisk/compiler.h" 00081 00082 #include "sip3.h" 00083 #include "sip3funcs.h" 00084 00085 /*! XXX Note that sip_methods[i].id == i must hold or the code breaks */ 00086 const struct cfsip_methods sip_methods[] = { 00087 { SIP_UNKNOWN, RTP, "-UNKNOWN-", CAN_NOT_CREATE_DIALOG}, 00088 { SIP_RESPONSE, NO_RTP, "SIP/2.0" , CAN_NOT_CREATE_DIALOG}, 00089 { SIP_REGISTER, NO_RTP, "REGISTER" , CAN_CREATE_DIALOG}, 00090 { SIP_OPTIONS, NO_RTP, "OPTIONS" , CAN_CREATE_DIALOG}, 00091 { SIP_NOTIFY, NO_RTP, "NOTIFY" , CAN_CREATE_DIALOG}, 00092 { SIP_INVITE, RTP, "INVITE" , CAN_CREATE_DIALOG}, 00093 { SIP_ACK, NO_RTP, "ACK" , CAN_NOT_CREATE_DIALOG}, 00094 { SIP_PRACK, NO_RTP, "PRACK" , CAN_NOT_CREATE_DIALOG}, 00095 { SIP_BYE, NO_RTP, "BYE" , CAN_NOT_CREATE_DIALOG}, 00096 { SIP_REFER, NO_RTP, "REFER" , CAN_CREATE_DIALOG}, 00097 { SIP_SUBSCRIBE, NO_RTP, "SUBSCRIBE" , CAN_CREATE_DIALOG}, 00098 { SIP_MESSAGE, NO_RTP, "MESSAGE" , CAN_CREATE_DIALOG}, 00099 { SIP_UPDATE, NO_RTP, "UPDATE" , CAN_NOT_CREATE_DIALOG}, 00100 { SIP_INFO, NO_RTP, "INFO" , CAN_NOT_CREATE_DIALOG}, 00101 { SIP_CANCEL, NO_RTP, "CANCEL" , CAN_NOT_CREATE_DIALOG}, 00102 { SIP_PUBLISH, NO_RTP, "PUBLISH", CAN_CREATE_DIALOG} 00103 }; 00104 00105 /*! \brief List of well-known SIP options. If we get this in a require, 00106 we should check the list and answer accordingly. */ 00107 static const struct cfsip_options sip_options[] = { /* XXX used in 3 places */ 00108 /* RFC3891: Replaces: header for transfer */ 00109 { SIP_OPT_REPLACES, SUPPORTED, "replaces" }, 00110 /* One version of Polycom firmware has the wrong label */ 00111 { SIP_OPT_REPLACES, SUPPORTED, "replace" }, 00112 /* RFC3262: PRACK 100% reliability */ 00113 { SIP_OPT_100REL, NOT_SUPPORTED, "100rel" }, 00114 /* RFC4028: SIP Session Timers */ 00115 { SIP_OPT_TIMER, NOT_SUPPORTED, "timer" }, 00116 /* RFC3959: SIP Early session support */ 00117 { SIP_OPT_EARLY_SESSION, NOT_SUPPORTED, "early-session" }, 00118 /* RFC3911: SIP Join header support */ 00119 { SIP_OPT_JOIN, NOT_SUPPORTED, "join" }, 00120 /* RFC3327: Path support */ 00121 { SIP_OPT_PATH, NOT_SUPPORTED, "path" }, 00122 /* RFC3840: Callee preferences */ 00123 { SIP_OPT_PREF, NOT_SUPPORTED, "pref" }, 00124 /* RFC3312: Precondition support */ 00125 { SIP_OPT_PRECONDITION, NOT_SUPPORTED, "precondition" }, 00126 /* RFC3323: Privacy with proxies*/ 00127 { SIP_OPT_PRIVACY, NOT_SUPPORTED, "privacy" }, 00128 /* RFC4092: Usage of the SDP ANAT Semantics in the SIP */ 00129 { SIP_OPT_SDP_ANAT, NOT_SUPPORTED, "sdp-anat" }, 00130 /* RFC3329: Security agreement mechanism */ 00131 { SIP_OPT_SEC_AGREE, NOT_SUPPORTED, "sec_agree" }, 00132 /* SIMPLE events: RFC4662 */ 00133 { SIP_OPT_EVENTLIST, NOT_SUPPORTED, "eventlist" }, 00134 /* GRUU: Globally Routable User Agent URI's */ 00135 { SIP_OPT_GRUU, NOT_SUPPORTED, "gruu" }, 00136 /* RFC4538: Target-dialog */ 00137 { SIP_OPT_TARGET_DIALOG,NOT_SUPPORTED, "tdialog" }, 00138 /* Disable the REFER subscription, RFC 4488 */ 00139 { SIP_OPT_NOREFERSUB, NOT_SUPPORTED, "norefersub" }, 00140 /* ietf-sip-history-info-06.txt */ 00141 { SIP_OPT_HISTINFO, NOT_SUPPORTED, "histinfo" }, 00142 /* ietf-sip-resource-priority-10.txt */ 00143 { SIP_OPT_RESPRIORITY, NOT_SUPPORTED, "resource-priority" }, 00144 }; 00145 00146 /*! \brief returns true if 'name' (with optional trailing whitespace) 00147 * matches the sip method 'id'. 00148 * Strictly speaking, SIP methods are case SENSITIVE, but we do 00149 * a case-insensitive comparison to be more tolerant. 00150 * following Jon Postel's rule: Be gentle in what you accept, strict with what you send 00151 */ 00152 int method_match(enum sipmethod id, const char *name) 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 } 00161 00162 /*! \brief find_sip_method: Find SIP method from header */ 00163 int find_sip_method(const char *msg) 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 } 00175 00176 /*! \brief return text string for sip method */ 00177 char *sip_method2txt(int method) 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 } 00188 00189 /*! \brief Check whether method needs RTP */ 00190 int sip_method_needrtp(int method) 00191 { 00192 return sip_methods[method].need_rtp; 00193 } 00194 00195 /*! \brief Get tag from packet 00196 * 00197 * \return Returns the pointer to the provided tag buffer, 00198 * or NULL if the tag was not found. 00199 */ 00200 const char *gettag(const char *header, char *tagbuf, int tagbufsize) 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 } 00215 00216 /*! \brief Check if sip option is known to us, avoid x- options (non-standard) */ 00217 int sip_option_lookup(const char *optionlabel) 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 } 00236 00237 /*! \brief copy SIP request (mostly used to save request for responses) */ 00238 void copy_request(struct sip_request *dst, const struct sip_request *src) 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 } 00263 00264 00265 /*! \brief Parse supported header in incoming packet */ 00266 unsigned int parse_sip_options(struct sip_dialog *pvt, const char *supported) 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 } 00296 00297 /*! \brief Return text representation of SIP option */ 00298 char *sip_option2text(int option) 00299 { 00300 return sip_options[option].text; 00301 } 00302 00303 /*! \brief Print options to cli */ 00304 void sip_options_print(int options, int fd) 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 } 00317 00318 00319 /*! \brief Find compressed SIP alias */ 00320 const char *find_alias(const char *name, const char *_default) 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 } 00356 00357 /*! \brief Translate referring cause 00358 */ 00359 static void sip_set_redirstr(struct sip_dialog *p, char *reason) { 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 } 00387 00388 00389 /*! \brief Get referring dnis */ 00390 int get_rdnis(struct sip_dialog *p, struct sip_request *oreq) 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 } 00443 00444 /*! \brief Find out who the call is for 00445 We use the INVITE request uri to find out 00446 Runs a dialplan lookup 00447 */ 00448 int get_destination(struct sip_dialog *p, struct sip_request *oreq) 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 } 00586 00587 const char *__get_header(struct sip_request *req, const char *name, int *start) 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 } 00629 00630 /*! \brief Get header from SIP request */ 00631 const char *get_header(struct sip_request *req, const char *name) 00632 { 00633 int start = 0; 00634 return __get_header(req, name, &start); 00635 } 00636 00637 /*! \brief Copy one header field from one request to another */ 00638 int copy_header(struct sip_request *req, struct sip_request *orig, const char *field) 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 } 00647 00648 /*! \brief Copy all headers from one request to another */ 00649 int copy_all_header(struct sip_request *req, struct sip_request *orig, const char *field) 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 } 00670 00671 /*! \brief Copy SIP VIA Headers from the request to the response 00672 \note If the client indicates that it wishes to know the port we received from, 00673 it adds ;rport without an argument to the topmost via header. We need to 00674 add the port number (from our point of view) to that parameter. 00675 We always add ;received=<ip address> to the topmost via header. 00676 Received: RFC 3261, rport RFC 3581 */ 00677 int copy_via_headers(struct sip_dialog *p, struct sip_request *req, struct sip_request *orig, const char *field) 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 } 00744 00745 /*! \brief Locate closing quote in a string, skipping escaped quotes. 00746 * optionally with a limit on the search. 00747 * start must be past the first quote. 00748 */ 00749 static const char *find_closing_quote(const char *start, const char *lim) 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 } 00759 00760 /*! \brief Pick out text in brackets from character string 00761 \return pointer to terminated stripped string 00762 \param tmp input string that will be modified 00763 Examples: 00764 00765 "foo" <bar> valid input, returns bar 00766 foo returns the whole string 00767 < "foo ... > returns the string between brackets 00768 < "foo... bogus (missing closing bracket), returns the whole string 00769 XXX maybe should still skip the opening bracket 00770 */ 00771 char *get_in_brackets(char *tmp) 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 } 00805 00806 /*! \brief Parse multiline SIP headers into one header */ 00807 GNURK int lws2sws(char *msgbuf, int len) 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 } 00850 00851 /*! \brief Generate 32 byte random string for callid's etc */ 00852 char *generate_random_string(char *buf, size_t size) 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 } 00863 00864 /*! \brief Parse first line of incoming SIP request */ 00865 int determine_firstline_parts(struct sip_request *req) 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 } 00904 00905 /*! \brief Check Contact: URI of SIP message */ 00906 void extract_uri(struct sip_dialog *p, struct sip_request *req) 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 } 00917 00918 /*! \brief Parse 302 Moved temporalily response */ 00919 void parse_moved_contact(struct sip_dialog *p, struct sip_request *req) 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 } 00960 00961 /*! \brief Parse a SIP message 00962 \note this function is used both on incoming and outgoing packets 00963 */ 00964 GNURK void parse_request(struct sip_request *req) 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 }