From ecbd67d74e3fa8925c5fc089316f59a64de2936f Mon Sep 17 00:00:00 2001 From: Brett Bryant Date: Tue, 1 Jul 2008 21:19:59 +0000 Subject: [PATCH] Merged revisions 127154 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ........ r127154 | bbryant | 2008-07-01 16:03:52 -0500 (Tue, 01 Jul 2008) | 2 lines Add a configuration option so the global outboundproxy can use tcptls without it being defined by each sip user. ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@127163 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 144 +++++++++++++++++++++++++--------------- configs/sip.conf.sample | 3 + 2 files changed, 93 insertions(+), 54 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 1fe20f874c..307e2e94da 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -410,6 +410,12 @@ enum st_refresher { SESSION_TIMER_REFRESHER_UAS /*!< Session is refreshed by the UAS */ }; +/*!< Define some SIP transports */ +enum sip_transport { + SIP_TRANSPORT_UDP = 1, + SIP_TRANSPORT_TCP = 1 << 1, + SIP_TRANSPORT_TLS = 1 << 2, +}; /*! \brief definition of a sip proxy server * @@ -421,6 +427,7 @@ struct sip_proxy { char name[MAXHOSTNAMELEN]; /*!< DNS name of domain/host or IP */ struct sockaddr_in ip; /*!< Currently used IP address and port */ time_t last_dnsupdate; /*!< When this was resolved */ + enum sip_transport transport; int force; /*!< If it's an outbound proxy, Force use of this outbound proxy for all outbound requests */ /* Room for a SRV record chain based on the name */ }; @@ -767,13 +774,6 @@ static int *sipsock_read_id; /*!< ID of IO entry for sipsock FD */ #define DEC_CALL_RINGING 2 #define INC_CALL_RINGING 3 -/*!< Define some SIP transports */ -enum sip_transport { - SIP_TRANSPORT_UDP = 1, - SIP_TRANSPORT_TCP = 1 << 1, - SIP_TRANSPORT_TLS = 1 << 2, -}; - /*!< The SIP socket definition */ struct sip_socket { enum sip_transport type; @@ -1708,6 +1708,7 @@ static const char *sip_get_callid(struct ast_channel *chan); static int handle_request_do(struct sip_request *req, struct sockaddr_in *sin); static int sip_standard_port(struct sip_socket s); static int sip_prepare_socket(struct sip_pvt *p); +static int sip_parse_host(char *line, int lineno, char **hostname, int *portnum, enum sip_transport *transport); /*--- Transmitting responses and requests */ static int sipsock_read(int *id, int fd, short events, void *ignore); @@ -2521,6 +2522,14 @@ static inline const char *get_transport(enum sip_transport t) return "UNKNOWN"; } +static inline const char *get_transport_pvt(struct sip_pvt *p) +{ + if (p->outboundproxy && p->outboundproxy->transport) + p->socket.type = p->outboundproxy->transport; + + return get_transport(p->socket.type); +} + /*! \brief Transmit SIP message Sends a SIP request or response on a given socket (in the pvt) Called by retrans_pkt, send_request, send_response and @@ -2531,7 +2540,7 @@ static int __sip_xmit(struct sip_pvt *p, char *data, int len) int res = 0; const struct sockaddr_in *dst = sip_real_dst(p); - ast_debug(1, "Trying to put '%.10s' onto %s socket...\n", data, get_transport(p->socket.type)); + ast_debug(1, "Trying to put '%.10s' onto %s socket destined for %s:%d\n", data, get_transport_pvt(p), ast_inet_ntoa(dst->sin_addr), htons(dst->sin_port)); if (sip_prepare_socket(p) < 0) return XMIT_ERROR; @@ -2575,7 +2584,7 @@ static void build_via(struct sip_pvt *p) /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ ast_string_field_build(p, via, "SIP/2.0/%s %s:%d;branch=z9hG4bK%08x%s", - get_transport(p->socket.type), + get_transport_pvt(p), ast_inet_ntoa(p->ourip.sin_addr), ntohs(p->ourip.sin_port), p->branch, rport); } @@ -6018,35 +6027,14 @@ static int sip_register(const char *value, int lineno) char buf[256] = ""; char *username = NULL; char *hostname=NULL, *secret=NULL, *authuser=NULL; - char *porta=NULL; char *callback=NULL; - char *trans=NULL; if (!value) return -1; ast_copy_string(buf, value, sizeof(buf)); - username = strstr(buf, "://"); - - if (username) { - *username = '\0'; - username += 3; - - trans = buf; - - if (!strcasecmp(trans, "udp")) - transport = SIP_TRANSPORT_UDP; - else if (!strcasecmp(trans, "tcp")) - transport = SIP_TRANSPORT_TCP; - else if (!strcasecmp(trans, "tls")) - transport = SIP_TRANSPORT_TLS; - else - ast_log(LOG_WARNING, "'%s' is not a valid transport value for registration '%s' at line '%d'\n", trans, value, lineno); - } else { - username = buf; - ast_debug(1, "no trans\n"); - } + sip_parse_host(buf, lineno, &username, &portnum, &transport); /* First split around the last '@' then parse the two components. */ hostname = strrchr(username, '@'); /* allow @ in the first part */ @@ -6070,18 +6058,6 @@ static int sip_register(const char *value, int lineno) *callback++ = '\0'; if (ast_strlen_zero(callback)) callback = "s"; - porta = strchr(hostname, ':'); - if (porta) { - *porta++ = '\0'; - portnum = atoi(porta); - if (portnum == 0) { - ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno); - return -1; - } - } else { - portnum = (transport == SIP_TRANSPORT_TLS) ? - STANDARD_TLS_PORT : STANDARD_SIP_PORT; - } if (!(reg = ast_calloc(1, sizeof(*reg)))) { ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n"); return -1; @@ -8515,7 +8491,7 @@ static void build_contact(struct sip_pvt *p) else ast_string_field_build(p, our_contact, "", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr)); } else - ast_string_field_build(p, our_contact, "", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ntohs(p->socket.port), get_transport(p->socket.type)); + ast_string_field_build(p, our_contact, "", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ntohs(p->socket.port), get_transport_pvt(p)); } /*! \brief Build the Remote Party-ID & From using callingpres options */ @@ -18288,6 +18264,10 @@ static int sip_prepare_socket(struct sip_pvt *p) if (s->fd != -1) return s->fd; + if (p->outboundproxy && p->outboundproxy->transport) { + s->type = p->outboundproxy->transport; + } + if (s->type & SIP_TRANSPORT_UDP) { s->fd = sipsock; return s->fd; @@ -18346,6 +18326,50 @@ static int sip_prepare_socket(struct sip_pvt *p) return s->fd; } +/*! + * \brief Small function to parse a config line for a host with a transport + * i.e. tls://www.google.com:8056 + */ +static int sip_parse_host(char *line, int lineno, char **hostname, int *portnum, enum sip_transport *transport) +{ + char *port; + + if ((*hostname = strstr(line, "://"))) { + *hostname += 3; + + if (!strncasecmp(line, "tcp", 3)) + *transport = SIP_TRANSPORT_TCP; + else if (!strncasecmp(line, "tls", 3)) + *transport = SIP_TRANSPORT_TLS; + else if (!strncasecmp(line, "udp", 3)) + *transport = SIP_TRANSPORT_UDP; + else + ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type on line %d of sip.conf. defaulting to udp.\n", line, lineno); + } else { + *hostname = line; + *transport = SIP_TRANSPORT_UDP; + } + + if ((port = strchr(*hostname, ':'))) { + *port++ = '\0'; + + if (!sscanf(port, "%u", portnum)) { + ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", port, lineno); + port = NULL; + } + } + + if (!port) { + if (*transport & SIP_TRANSPORT_TLS) { + *portnum = STANDARD_TLS_PORT; + } else { + *portnum = STANDARD_SIP_PORT; + } + } + + return 0; +} + /*! * \brief Get cached MWI info * \retval 0 At least one message is waiting @@ -20548,21 +20572,33 @@ static int reload_config(enum channelreloadreason reason) } else if (!strcasecmp(v->name, "fromdomain")) { ast_copy_string(default_fromdomain, v->value, sizeof(default_fromdomain)); } else if (!strcasecmp(v->name, "outboundproxy")) { - char *name, *port = NULL, *force; + int portnum; + char *tok, *proxyname; - name = ast_strdupa(v->value); - if ((port = strchr(name, ':'))) { - *port++ = '\0'; - global_outboundproxy.ip.sin_port = htons(atoi(port)); + if (ast_strlen_zero(v->value)) { + ast_log(LOG_WARNING, "no value given for outbound proxy on line %d of sip.conf.", v->lineno); + continue; } - if ((force = strchr(port ? port : name, ','))) { - *force++ = '\0'; - global_outboundproxy.force = (!strcasecmp(force, "force")); + tok = ast_skip_blanks(strtok(ast_strdupa(v->value), ",")); + + sip_parse_host(tok, v->lineno, &proxyname, &portnum, &global_outboundproxy.transport); + + global_outboundproxy.ip.sin_port = htons(portnum); + + if ((tok = strtok(NULL, ","))) { + global_outboundproxy.force = !strncasecmp(ast_skip_blanks(tok), "force", 5); + } else { + global_outboundproxy.force = FALSE; + } + + if (ast_strlen_zero(proxyname)) { + ast_log(LOG_WARNING, "you must specify a name for the outboundproxy on line %d of sip.conf.", v->lineno); + global_outboundproxy.name[0] = '\0'; + continue; } - ast_copy_string(global_outboundproxy.name, name, sizeof(global_outboundproxy.name)); - proxy_update(&global_outboundproxy); + ast_copy_string(global_outboundproxy.name, proxyname, sizeof(global_outboundproxy.name)); } else if (!strcasecmp(v->name, "autocreatepeer")) { autocreatepeer = ast_true(v->value); } else if (!strcasecmp(v->name, "match_auth_username")) { diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index 3bca1523ea..f5c16612c0 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -233,6 +233,9 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ;outboundproxy=proxy.provider.domain ; send outbound signaling to this proxy, not directly to the devices ;outboundproxy=proxy.provider.domain:8080 ; send outbound signaling to this proxy, not directly to the devices ;outboundproxy=proxy.provider.domain,force ; Send ALL outbound signalling to proxy, ignoring route: headers +;outboundproxy=tls://proxy.provider.domain ; same as '=proxy.provider.domain' except we try to connect with tls +; ; (could also be tcp,udp) - defining transports on the proxy line only +; ; applies for the global proxy, otherwise use the transport= option ;matchexterniplocally = yes ; Only substitute the externip or externhost setting if it matches ; your localnet setting. Unless you have some sort of strange network ; setup you will not need to enable this.