[asterisk-commits] mjordan: trunk r387135 - in /trunk: ./ channels/chan_sip.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed May 1 13:38:41 CDT 2013
Author: mjordan
Date: Wed May 1 13:38:40 2013
New Revision: 387135
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=387135
Log:
Prevent crash in 'sip show peers' when the number of peers on a system is large
When you have lots of SIP peers (according to the issue reporter, around 3500),
the 'sip show peers' CLI command or AMI action can crash due to a poorly placed
string duplication that occurs on the stack. This patch refactors the command
to not allocate the string on the stack, and handles the formatting of a single
peer in a separate function call.
(closes issue ASTERISK-21466)
Reported by: Guillaume Knispel
patches:
fix_sip_show_peers_stack_overflow_asterisk_11.3.0-v2.patch uploaded by gknispel (License 6492)
........
Merged revisions 387134 from http://svn.asterisk.org/svn/asterisk/branches/11
Modified:
trunk/ (props changed)
trunk/channels/chan_sip.c
Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.
Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=387135&r1=387134&r2=387135
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Wed May 1 13:38:40 2013
@@ -384,7 +384,7 @@
<para>Since there are several headers (such as Via) which can occur multiple
times, SIP_HEADER takes an optional second argument to specify which header with
that name to retrieve. Headers start at offset <literal>1</literal>.</para>
- <para>Please observe that contents of the SDP (an attachment to the
+ <para>Please observe that contents of the SDP (an attachment to the
SIP request) can't be accessed with this function.</para>
</description>
</function>
@@ -1118,6 +1118,8 @@
struct ao2_container *sip_monitor_instances;
+struct show_peers_context;
+
/*---------------------------- Forward declarations of functions in chan_sip.c */
/* Note: This is added to help splitting up chan_sip.c into several files
in coming releases. */
@@ -1295,6 +1297,7 @@
static int peer_status(struct sip_peer *peer, char *status, int statuslen);
static char *sip_show_sched(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static char * _sip_show_peers(int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[]);
+static struct sip_peer *_sip_show_peers_one(int fd, struct mansession *s, struct show_peers_context *cont, struct sip_peer *peer);
static char *sip_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static char *sip_show_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static void print_group(int fd, ast_group_t group, int crlf);
@@ -1580,7 +1583,7 @@
};
/* -------- End of declarations of structures, constants and forward declarations of functions
- Below starts actual code
+ Below starts actual code
------------------------
*/
@@ -2734,7 +2737,7 @@
size_t datalen = ast_str_strlen(req->data);
char buf[1024] = "";
int timeout = -1;
-
+
/* Read in headers one line at a time */
while (datalen < 4 || strncmp(REQ_OFFSET_TO_STR(req, data->used - 4), "\r\n\r\n", 4)) {
if (!tcptls_session->client && !authenticated) {
@@ -2843,7 +2846,7 @@
}
content_length -= strlen(buf);
ast_str_append(&req->data, 0, "%s", buf);
-
+
datalen = ast_str_strlen(req->data);
if (datalen > SIP_MAX_PACKET_SIZE) {
ast_log(LOG_WARNING, "Rejecting TLS packet from '%s' because way too large: %zu\n",
@@ -3064,7 +3067,7 @@
ast_str_append(&req->data, 0, "%s", ast_str_buffer(tcptls_session->overflow_buf));
ast_str_reset(tcptls_session->overflow_buf);
}
-
+
datalen = ast_str_strlen(req->data);
if (datalen > SIP_MAX_PACKET_SIZE) {
ast_log(LOG_WARNING, "Rejecting TCP packet from '%s' because way too large: %zu\n",
@@ -3195,7 +3198,7 @@
}
}
- /*
+ /*
* handle the socket event, check for both reads from the socket fd or TCP overflow buffer,
* and writes from alert_pipe fd.
*/
@@ -3493,7 +3496,7 @@
AST_SCHED_DEL_UNREF(sched, dialog->waitid, dialog_unref(dialog, "when you delete the waitid sched, you should dec the refcount for the stored dialog ptr"));
AST_SCHED_DEL_UNREF(sched, dialog->initid, dialog_unref(dialog, "when you delete the initid sched, you should dec the refcount for the stored dialog ptr"));
-
+
if (dialog->autokillid > -1) {
AST_SCHED_DEL_UNREF(sched, dialog->autokillid, dialog_unref(dialog, "when you delete the autokillid sched, you should dec the refcount for the stored dialog ptr"));
}
@@ -3714,7 +3717,7 @@
static int find_sip_method(const char *msg)
{
int i, res = 0;
-
+
if (ast_strlen_zero(msg)) {
return 0;
}
@@ -5622,7 +5625,7 @@
* Checks the "sipregs" realtime family from extconfig.conf if it's configured.
* This returns a pointer to a peer and because we use build_peer, we can rest
* assured that the refcount is bumped.
- *
+ *
* \note This is never called with both newpeername and addr at the same time.
* If you do, be prepared to get a peer with a different name than newpeername.
*/
@@ -6284,7 +6287,7 @@
* an A record lookup should be used instead of SRV.
*/
if (!hostport.port && sip_cfg.srvlookup) {
- snprintf(service, sizeof(service), "_%s._%s.%s",
+ snprintf(service, sizeof(service), "_%s._%s.%s",
get_srv_service(dialog->socket.type),
get_srv_protocol(dialog->socket.type), peername);
if ((srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno,
@@ -6545,7 +6548,7 @@
mwi->call->mwi = NULL;
sip_destroy(mwi->call);
}
-
+
AST_SCHED_DEL(sched, mwi->resub);
ast_string_field_free_memory(mwi);
ast_free(mwi);
@@ -6601,16 +6604,16 @@
p->relatedpeer->mwipvt = dialog_unref(p->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt");
if (p->relatedpeer && p->relatedpeer->call == p)
p->relatedpeer->call = dialog_unref(p->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself");
-
+
if (p->relatedpeer)
p->relatedpeer = sip_unref_peer(p->relatedpeer,"unsetting a dialog relatedpeer field in sip_destroy");
-
+
if (p->registry) {
if (p->registry->call == p)
p->registry->call = dialog_unref(p->registry->call, "nulling out the registry's call dialog field in unlink_all");
p->registry = registry_unref(p->registry, "delete p->registry");
}
-
+
if (p->mwi) {
p->mwi->call = NULL;
p->mwi = NULL;
@@ -7294,8 +7297,8 @@
} else {
/* Note we will need a BYE when this all settles out
but we can't send one while we have "INVITE" outstanding. */
- ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
- ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE);
+ ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
+ ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE);
AST_SCHED_DEL_UNREF(sched, p->waitid, dialog_unref(p, "when you delete the waitid sched, you should dec the refcount for the stored dialog ptr"));
if (sip_cancel_destroy(p)) {
ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
@@ -7331,7 +7334,7 @@
codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC");
}
- if (!codec)
+ if (!codec)
return;
ast_getformatbyname(codec, &fmt);
@@ -7802,7 +7805,7 @@
if (ast_channel_state(ast) == AST_STATE_RING) {
p->invitestate = INV_EARLY_MEDIA;
if (!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) ||
- (ast_test_flag(&p->flags[0], SIP_PROG_INBAND) == SIP_PROG_INBAND_NEVER)) {
+ (ast_test_flag(&p->flags[0], SIP_PROG_INBAND) == SIP_PROG_INBAND_NEVER)) {
/* Send 180 ringing if out-of-band seems reasonable */
transmit_provisional_response(p, "180 Ringing", &p->initreq, 0);
ast_set_flag(&p->flags[0], SIP_RINGING);
@@ -7992,7 +7995,7 @@
{
const char *my_name; /* pick a good name */
-
+
if (title) {
my_name = title;
} else {
@@ -8142,7 +8145,7 @@
struct ast_tone_zone *zone;
if (!(zone = ast_get_indication_zone(i->zone))) {
ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", i->zone);
- }
+ }
ast_channel_zone_set(tmp, zone);
}
i->owner = tmp;
@@ -8411,7 +8414,7 @@
{
/* Retrieve audio/etc from channel. Assumes p->lock is already held. */
struct ast_frame *f;
-
+
if (!p->rtp) {
/* We have no RTP allocated for this channel */
return &ast_null_frame;
@@ -8811,7 +8814,7 @@
p->do_history = recordhistory;
- p->branch = ast_random();
+ p->branch = ast_random();
make_our_tag(p);
p->ocseq = INITIAL_CSEQ;
p->allowed_methods = UINT_MAX;
@@ -9011,14 +9014,14 @@
/*
* Compare incoming request against initial transaction.
- *
+ *
* This is a best effort attempt at distinguishing forked requests from
* our initial transaction. If all the elements are NOT in place to evaluate
* this, this block is ignored and the dialog match is made regardless.
* Once the totag is established after the dialog is confirmed, this is not necessary.
*
* CRITERIA required for initial transaction matching.
- *
+ *
* 1. Is a Request
* 2. Callid and theirtag match (this is done in the dialog matching block)
* 3. totag is NOT present
@@ -9613,7 +9616,7 @@
static unsigned int set_pvt_allowed_methods(struct sip_pvt *pvt, struct sip_request *req)
{
pvt->allowed_methods = parse_allowed_methods(req);
-
+
if (ast_test_flag(&pvt->flags[1], SIP_PAGE2_RPID_UPDATE)) {
mark_method_allowed(&pvt->allowed_methods, SIP_UPDATE);
}
@@ -9849,7 +9852,7 @@
}
if (!strcasecmp(line, "Content-Type: application/sdp"))
found_application_sdp = TRUE;
-
+
if (ast_strlen_zero(line)) {
if (found_application_sdp && !found_end_of_headers){
req->sdp_start = x;
@@ -11397,12 +11400,12 @@
req->headers++;
- return 0;
-}
-
-/*!
+ return 0;
+}
+
+/*!
* \pre dialog is assumed to be locked while calling this function
- * \brief Add 'Max-Forwards' header to SIP message
+ * \brief Add 'Max-Forwards' header to SIP message
*/
static int add_max_forwards(struct sip_pvt *dialog, struct sip_request *req)
{
@@ -11940,7 +11943,7 @@
sizeof(stripped));
n = get_in_brackets(stripped);
c = remove_uri_parameters(n);
- }
+ }
init_req(req, sipmethod, c);
snprintf(tmp, sizeof(tmp), "%u %s", seqno, sip_methods[sipmethod].text);
@@ -12372,7 +12375,7 @@
}
}
}
-
+
/* Use default realm from config file */
ast_string_field_set(p, realm, sip_cfg.realm);
}
@@ -13696,7 +13699,7 @@
INVITE that opened the SIP dialogue
We reinvite so that the audio stream (RTP) go directly between
the SIP UAs. SIP Signalling stays with * in the path.
-
+
If t38version is TRUE, we send T38 SDP for re-invite from audio/video to
T38 UDPTL transmission on the channel
@@ -13707,7 +13710,7 @@
static int transmit_reinvite_with_sdp(struct sip_pvt *p, int t38version, int oldsdp)
{
struct sip_request req;
-
+
reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ? SIP_UPDATE : SIP_INVITE, 0, 1);
add_header(&req, "Allow", ALLOWED_METHODS);
@@ -13932,7 +13935,7 @@
/* If custom URI options have been provided, append them */
if (p->options && !ast_strlen_zero(p->options->uri_options))
ast_str_append(&invite, 0, ";%s", p->options->uri_options);
-
+
/* This is the request URI, which is the next hop of the call
which may or may not be the destination of the call
*/
@@ -14084,7 +14087,7 @@
return 0;
}
-/*!
+/*!
* \brief Build REFER/INVITE/OPTIONS/SUBSCRIBE message and transmit it
* \param p sip_pvt structure
* \param sipmethod
@@ -14150,7 +14153,7 @@
}
p->stimer->st_active = TRUE;
- if (st_get_mode(p, 0) == SESSION_TIMER_MODE_ORIGINATE) {
+ if (st_get_mode(p, 0) == SESSION_TIMER_MODE_ORIGINATE) {
snprintf(i2astr, sizeof(i2astr), "%d", p->stimer->st_interval);
add_header(&req, "Session-Expires", i2astr);
}
@@ -14166,7 +14169,7 @@
|| (p->refer && global_refer_addheaders))) {
struct ast_channel *chan = p->owner; /* The owner channel */
struct varshead *headp;
-
+
ast_channel_lock(chan);
headp = ast_channel_varshead(chan);
@@ -14258,15 +14261,15 @@
static int sip_subscribe_mwi_do(const void *data)
{
struct sip_subscription_mwi *mwi = (struct sip_subscription_mwi*)data;
-
+
if (!mwi) {
return -1;
}
-
+
mwi->resub = -1;
__sip_subscribe_mwi_do(mwi);
ASTOBJ_UNREF(mwi, sip_subscribe_mwi_destroy);
-
+
return 0;
}
@@ -14358,7 +14361,7 @@
transmit_invite(mwi->call, SIP_SUBSCRIBE, 0, 0, NULL);
return 0;
}
-
+
/* Create a dialog that we will use for the subscription */
if (!(mwi->call = sip_alloc(NULL, NULL, 0, SIP_SUBSCRIBE, NULL, NULL))) {
return -1;
@@ -14369,7 +14372,7 @@
if (!ast_sockaddr_port(&mwi->us) && mwi->portno) {
ast_sockaddr_set_port(&mwi->us, mwi->portno);
}
-
+
/* Setup the destination of our subscription */
if (create_addr(mwi->call, mwi->hostname, &mwi->us, 0)) {
dialog_unlink_all(mwi->call);
@@ -14378,14 +14381,14 @@
}
mwi->call->expiry = mwi_expiry;
-
+
if (!mwi->dnsmgr && mwi->portno) {
ast_sockaddr_set_port(&mwi->call->sa, mwi->portno);
ast_sockaddr_set_port(&mwi->call->recv, mwi->portno);
} else {
mwi->portno = ast_sockaddr_port(&mwi->call->sa);
}
-
+
/* Set various other information */
if (!ast_strlen_zero(mwi->authuser)) {
ast_string_field_set(mwi->call, peername, mwi->authuser);
@@ -14410,7 +14413,7 @@
change_callid_pvt(mwi->call, NULL);
ast_set_flag(&mwi->call->flags[0], SIP_OUTGOING);
-
+
/* Associate the call with us */
mwi->call->mwi = ASTOBJ_REF(mwi);
@@ -14867,7 +14870,7 @@
{
struct sip_request req;
char tmp[SIPBUFSIZE/2];
-
+
reqprep(&req, p, SIP_NOTIFY, 0, 1);
snprintf(tmp, sizeof(tmp), "refer;id=%d", cseq);
add_header(&req, "Event", tmp);
@@ -14993,7 +14996,7 @@
ast_set_flag(&p->flags[0], SIP_OUTGOING);
p->invitestate = INV_CALLING;
send_request(p, &req, XMIT_CRITICAL, p->ocseq);
- } else if ((is_method_allowed(&p->allowed_methods, SIP_UPDATE)) && (!ast_strlen_zero(p->okcontacturi))) {
+ } else if ((is_method_allowed(&p->allowed_methods, SIP_UPDATE)) && (!ast_strlen_zero(p->okcontacturi))) {
reqprep(&req, p, SIP_UPDATE, 0, 1);
add_rpid(&req, p);
add_header(&req, "X-Asterisk-rpid-update", "Yes");
@@ -15076,8 +15079,8 @@
return 0;
}
-/*! \brief Register with SIP proxy
- \return see \ref __sip_xmit
+/*! \brief Register with SIP proxy
+ \return see \ref __sip_xmit
*/
static int __sip_do_register(struct sip_registry *r)
{
@@ -15228,7 +15231,7 @@
ast_log(LOG_WARNING, "Unable to allocate registration transaction (memory or socket error)\n");
return 0;
}
-
+
if (p->do_history) {
append_history(p, "RegistryInit", "Account: %s@%s", r->username, r->hostname);
}
@@ -15574,7 +15577,7 @@
static int transmit_info_with_digit(struct sip_pvt *p, const char digit, unsigned int duration)
{
struct sip_request req;
-
+
reqprep(&req, p, SIP_INFO, 0, 1);
add_digit(&req, digit, duration, (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_SHORTINFO));
return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
@@ -15584,7 +15587,7 @@
static int transmit_info_with_vidupdate(struct sip_pvt *p)
{
struct sip_request req;
-
+
reqprep(&req, p, SIP_INFO, 0, 1);
add_vidupdate(&req);
return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
@@ -15596,7 +15599,7 @@
static int transmit_request(struct sip_pvt *p, int sipmethod, uint32_t seqno, enum xmittype reliable, int newbranch)
{
struct sip_request resp;
-
+
reqprep(&resp, p, sipmethod, seqno, newbranch);
if (sipmethod == SIP_CANCEL && p->answered_elsewhere) {
add_header(&resp, "Reason", "SIP;cause=200;text=\"Call completed elsewhere\"");
@@ -15628,7 +15631,7 @@
static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, uint32_t seqno, enum xmittype reliable, int newbranch)
{
struct sip_request resp;
-
+
reqprep(&resp, p, sipmethod, seqno, newbranch);
if (!ast_strlen_zero(p->realm)) {
char digest[1024];
@@ -15670,7 +15673,7 @@
break;
}
- return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);
+ return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);
}
/*! \brief Remove registration data from realtime database or AST/DB when registration expires */
@@ -15870,7 +15873,7 @@
/* We should return false for URI:s we can't handle,
like tel:, mailto:,ldap: etc */
- return TRUE;
+ return TRUE;
}
/*! \brief parse uri in a way that allows semicolon stripping if legacy mode is enabled
@@ -15901,7 +15904,7 @@
ast_copy_string(contact_buf, fullcontact, sizeof(contact_buf));
contact = contact_buf;
- /*
+ /*
* We have only the part in <brackets> here so we just need to parse a SIP URI.
*
* Note: The outbound proxy could be using UDP between the proxy and Asterisk.
@@ -16458,7 +16461,7 @@
return 0;
}
-/*! \brief builds the sip_pvt's nonce field which is used for the authentication
+/*! \brief builds the sip_pvt's nonce field which is used for the authentication
* challenge. When forceupdate is not set, the nonce is only updated if
* the current one is stale. In this case, a stalenonce is one which
* has already received a response, if a nonce has not received a response
@@ -17376,7 +17379,7 @@
if (!cid_name) {
no_name = 1;
cid_name = (char *)emptyname;
- }
+ }
/* Only return true if the supplied caller id is different */
if (!strcasecmp(p->cid_num, cid_num) && !strcasecmp(p->cid_name, cid_name) && p->callingpres == callingpres) {
do_update = 0;
@@ -17878,7 +17881,7 @@
sip_pvt_lock(sip_pvt_ptr);
}
}
-
+
return sip_pvt_ptr;
}
@@ -17971,7 +17974,7 @@
to = strcasestr(ptr, "to-tag=");
from = strcasestr(ptr, "from-tag=");
}
-
+
/* Grab the to header */
if (to) {
ptr = to + 7;
@@ -18861,7 +18864,7 @@
int showall = FALSE;
struct ao2_iterator i;
struct sip_peer *peer;
-
+
switch (cmd) {
case CLI_INIT:
e->command = "sip show inuse";
@@ -18879,7 +18882,7 @@
if (a->argc == 4 && !strcmp(a->argv[3], "all"))
showall = TRUE;
-
+
ast_cli(a->fd, FORMAT, "* Peer name", "In use", "Limit");
i = ao2_iterator_init(peers, 0);
@@ -19158,7 +19161,7 @@
"ListItems: %d\r\n"
"%s"
"\r\n", total, idtext);
-
+
return 0;
}
@@ -19214,46 +19217,58 @@
return strcmp((*ap)->name, (*bp)->name);
}
+/* the last argument is left-aligned, so we don't need a size anyways */
+#define PEERS_FORMAT2 "%-25.25s %-39.39s %-3.3s %-10.10s %-3.3s %-8s %-11s %-32.32s %s\n"
+
+/*! \brief Used in the sip_show_peers functions to pass parameters */
+struct show_peers_context {
+ regex_t regexbuf;
+ int havepattern;
+ char idtext[256];
+ int realtimepeers;
+ int peers_mon_online;
+ int peers_mon_offline;
+ int peers_unmon_offline;
+ int peers_unmon_online;
+};
/*! \brief Execute sip show peers command */
static char *_sip_show_peers(int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[])
{
- regex_t regexbuf;
- int havepattern = FALSE;
+ struct show_peers_context cont = {
+ .havepattern = FALSE,
+ .idtext = "",
+
+ .peers_mon_online = 0,
+ .peers_mon_offline = 0,
+ .peers_unmon_online = 0,
+ .peers_unmon_offline = 0,
+ };
+
struct sip_peer *peer;
struct ao2_iterator* it_peers;
-/* the last argument is left-aligned, so we don't need a size anyways */
-#define FORMAT2 "%-25.25s %-39.39s %-3.3s %-10.10s %-3.3s %-8s %-11s %-32.32s %s\n"
-
- char name[256];
int total_peers = 0;
- int peers_mon_online = 0;
- int peers_mon_offline = 0;
- int peers_unmon_offline = 0;
- int peers_unmon_online = 0;
const char *id;
- char idtext[256] = "";
- int realtimepeers;
struct sip_peer **peerarray;
int k;
- realtimepeers = ast_check_realtime("sippeers");
+ cont.realtimepeers = ast_check_realtime("sippeers");
if (s) { /* Manager - get ActionID */
id = astman_get_header(m, "ActionID");
if (!ast_strlen_zero(id)) {
- snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
+ snprintf(cont.idtext, sizeof(cont.idtext), "ActionID: %s\r\n", id);
}
}
switch (argc) {
case 5:
if (!strcasecmp(argv[3], "like")) {
- if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) {
+ if (regcomp(&cont.regexbuf, argv[4], REG_EXTENDED | REG_NOSUB)) {
return CLI_SHOWUSAGE;
}
- havepattern = TRUE;
+ cont.havepattern = TRUE;
} else {
return CLI_SHOWUSAGE;
}
@@ -19265,7 +19280,7 @@
if (!s) {
/* Normal list */
- ast_cli(fd, FORMAT2, "Name/username", "Host", "Dyn", "Forcerport", "ACL", "Port", "Status", "Description", (realtimepeers ? "Realtime" : ""));
+ ast_cli(fd, PEERS_FORMAT2, "Name/username", "Host", "Dyn", "Forcerport", "ACL", "Port", "Status", "Description", (cont.realtimepeers ? "Realtime" : ""));
}
ao2_lock(peers);
@@ -19291,7 +19306,7 @@
continue;
}
- if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) {
+ if (cont.havepattern && regexec(&cont.regexbuf, peer->name, 0, NULL, 0)) {
ao2_unlock(peer);
sip_unref_peer(peer, "toss iterator peer ptr before continue");
continue;
@@ -19305,110 +19320,16 @@
qsort(peerarray, total_peers, sizeof(struct sip_peer *), peercomparefunc);
for(k = 0; k < total_peers; k++) {
- char status[20] = "";
- char pstatus;
-
- /*
- * tmp_port and tmp_host store copies of ast_sockaddr_stringify strings since the
- * string pointers for that function aren't valid between subsequent calls to
- * ast_sockaddr_stringify functions
- */
- char *tmp_port;
- char *tmp_host;
-
- peer = peerarray[k];
-
- tmp_port = ast_sockaddr_isnull(&peer->addr) ?
- "0" : ast_strdupa(ast_sockaddr_stringify_port(&peer->addr));
-
- tmp_host = ast_sockaddr_isnull(&peer->addr) ?
- "(Unspecified)" : ast_strdupa(ast_sockaddr_stringify_addr(&peer->addr));
-
- ao2_lock(peer);
- if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) {
- ao2_unlock(peer);
- peer = peerarray[k] = sip_unref_peer(peer, "toss iterator peer ptr before continue");
- continue;
- }
-
- if (!ast_strlen_zero(peer->username) && !s) {
- snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
- } else {
- ast_copy_string(name, peer->name, sizeof(name));
- }
-
- pstatus = peer_status(peer, status, sizeof(status));
- if (pstatus == 1) {
- peers_mon_online++;
- } else if (pstatus == 0) {
- peers_mon_offline++;
- } else {
- if (ast_sockaddr_isnull(&peer->addr) ||
- !ast_sockaddr_port(&peer->addr)) {
- peers_unmon_offline++;
- } else {
- peers_unmon_online++;
- }
- }
-
- if (!s) { /* Normal CLI list */
- ast_cli(fd, FORMAT2, name,
- tmp_host,
- peer->host_dynamic ? " D " : " ", /* Dynamic or not? */
- ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT) ?
- ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " A " : " a " :
- ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : " ", /* NAT=yes? */
- (!ast_acl_list_is_empty(peer->acl)) ? " A " : " ", /* permit/deny */
- tmp_port, status,
- peer->description ? peer->description : "",
- realtimepeers ? (peer->is_realtime ? "Cached RT" : "") : "");
- } else { /* Manager format */
- /* The names here need to be the same as other channels */
- astman_append(s,
- "Event: PeerEntry\r\n%s"
- "Channeltype: SIP\r\n"
- "ObjectName: %s\r\n"
- "ChanObjectType: peer\r\n" /* "peer" or "user" */
- "IPaddress: %s\r\n"
- "IPport: %s\r\n"
- "Dynamic: %s\r\n"
- "AutoForcerport: %s\r\n"
- "Forcerport: %s\r\n"
- "AutoComedia: %s\r\n"
- "Comedia: %s\r\n"
- "VideoSupport: %s\r\n"
- "TextSupport: %s\r\n"
- "ACL: %s\r\n"
- "Status: %s\r\n"
- "RealtimeDevice: %s\r\n"
- "Description: %s\r\n\r\n",
- idtext,
- peer->name,
- ast_sockaddr_isnull(&peer->addr) ? "-none-" : tmp_host,
- ast_sockaddr_isnull(&peer->addr) ? "0" : tmp_port,
- peer->host_dynamic ? "yes" : "no", /* Dynamic or not? */
- ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT) ? "yes" : "no",
- ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "yes" : "no", /* NAT=yes? */
- ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA) ? "yes" : "no",
- ast_test_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP) ? "yes" : "no",
- ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no", /* VIDEOSUPPORT=yes? */
- ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no", /* TEXTSUPPORT=yes? */
- ast_acl_list_is_empty(peer->acl) ? "no" : "yes", /* permit/deny/acl */
- status,
- realtimepeers ? (peer->is_realtime ? "yes" : "no") : "no",
- peer->description);
- }
- ao2_unlock(peer);
- peer = peerarray[k] = sip_unref_peer(peer, "toss iterator peer ptr");
+ peerarray[k] = _sip_show_peers_one(fd, s, &cont, peerarray[k]);
}
if (!s) {
ast_cli(fd, "%d sip peers [Monitored: %d online, %d offline Unmonitored: %d online, %d offline]\n",
- total_peers, peers_mon_online, peers_mon_offline, peers_unmon_online, peers_unmon_offline);
- }
-
- if (havepattern) {
- regfree(®exbuf);
+ total_peers, cont.peers_mon_online, cont.peers_mon_offline, cont.peers_unmon_online, cont.peers_unmon_offline);
+ }
+
+ if (cont.havepattern) {
+ regfree(&cont.regexbuf);
}
if (total) {
@@ -19418,15 +19339,118 @@
ast_free(peerarray);
return CLI_SUCCESS;
-#undef FORMAT2
-}
+}
+
+/*! \brief Emit informations for one peer during sip show peers command */
+static struct sip_peer *_sip_show_peers_one(int fd, struct mansession *s, struct show_peers_context *cont, struct sip_peer *peer)
+{
+ /* _sip_show_peers_one() is separated from _sip_show_peers() to properly free the ast_strdupa
+ * (this is executed in a loop in _sip_show_peers() )
+ */
+
+ char name[256];
+ char status[20] = "";
+ char pstatus;
+
+ /*
+ * tmp_port and tmp_host store copies of ast_sockaddr_stringify strings since the
+ * string pointers for that function aren't valid between subsequent calls to
+ * ast_sockaddr_stringify functions
+ */
+ char *tmp_port;
+ char *tmp_host;
+
+ tmp_port = ast_sockaddr_isnull(&peer->addr) ?
+ "0" : ast_strdupa(ast_sockaddr_stringify_port(&peer->addr));
+
+ tmp_host = ast_sockaddr_isnull(&peer->addr) ?
+ "(Unspecified)" : ast_strdupa(ast_sockaddr_stringify_addr(&peer->addr));
+
+ ao2_lock(peer);
+ if (cont->havepattern && regexec(&cont->regexbuf, peer->name, 0, NULL, 0)) {
+ ao2_unlock(peer);
+ return sip_unref_peer(peer, "toss iterator peer ptr no match");
+ }
+
+ if (!ast_strlen_zero(peer->username) && !s) {
+ snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
+ } else {
+ ast_copy_string(name, peer->name, sizeof(name));
+ }
+
+ pstatus = peer_status(peer, status, sizeof(status));
+ if (pstatus == 1) {
+ cont->peers_mon_online++;
+ } else if (pstatus == 0) {
+ cont->peers_mon_offline++;
+ } else {
+ if (ast_sockaddr_isnull(&peer->addr) ||
+ !ast_sockaddr_port(&peer->addr)) {
+ cont->peers_unmon_offline++;
+ } else {
+ cont->peers_unmon_online++;
+ }
+ }
+
+ if (!s) { /* Normal CLI list */
+ ast_cli(fd, PEERS_FORMAT2, name,
+ tmp_host,
+ peer->host_dynamic ? " D " : " ", /* Dynamic or not? */
+ ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT) ?
+ ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " A " : " a " :
+ ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : " ", /* NAT=yes? */
+ (!ast_acl_list_is_empty(peer->acl)) ? " A " : " ", /* permit/deny */
+ tmp_port, status,
+ peer->description ? peer->description : "",
+ cont->realtimepeers ? (peer->is_realtime ? "Cached RT" : "") : "");
+ } else { /* Manager format */
+ /* The names here need to be the same as other channels */
+ astman_append(s,
+ "Event: PeerEntry\r\n%s"
+ "Channeltype: SIP\r\n"
+ "ObjectName: %s\r\n"
+ "ChanObjectType: peer\r\n" /* "peer" or "user" */
+ "IPaddress: %s\r\n"
+ "IPport: %s\r\n"
+ "Dynamic: %s\r\n"
+ "AutoForcerport: %s\r\n"
+ "Forcerport: %s\r\n"
+ "AutoComedia: %s\r\n"
+ "Comedia: %s\r\n"
+ "VideoSupport: %s\r\n"
+ "TextSupport: %s\r\n"
+ "ACL: %s\r\n"
+ "Status: %s\r\n"
+ "RealtimeDevice: %s\r\n"
+ "Description: %s\r\n\r\n",
+ cont->idtext,
+ peer->name,
+ ast_sockaddr_isnull(&peer->addr) ? "-none-" : tmp_host,
+ ast_sockaddr_isnull(&peer->addr) ? "0" : tmp_port,
+ peer->host_dynamic ? "yes" : "no", /* Dynamic or not? */
+ ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT) ? "yes" : "no",
+ ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "yes" : "no", /* NAT=yes? */
+ ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA) ? "yes" : "no",
+ ast_test_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP) ? "yes" : "no",
+ ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no", /* VIDEOSUPPORT=yes? */
+ ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no", /* TEXTSUPPORT=yes? */
+ ast_acl_list_is_empty(peer->acl) ? "no" : "yes", /* permit/deny/acl */
+ status,
+ cont->realtimepeers ? (peer->is_realtime ? "yes" : "no") : "no",
+ peer->description);
+ }
+ ao2_unlock(peer);
+
+ return sip_unref_peer(peer, "toss iterator peer ptr");
+}
+#undef PEERS_FORMAT2
static int peer_dump_func(void *userobj, void *arg, int flags)
{
struct sip_peer *peer = userobj;
int refc = ao2_t_ref(userobj, 0, "");
struct ast_cli_args *a = (struct ast_cli_args *) arg;
-
+
ast_cli(a->fd, "name: %s\ntype: peer\nobjflags: %d\nrefcount: %d\n\n",
peer->name, 0, refc);
return 0;
@@ -19437,7 +19461,7 @@
struct sip_pvt *pvt = userobj;
int refc = ao2_t_ref(userobj, 0, "");
struct ast_cli_args *a = (struct ast_cli_args *) arg;
-
+
ast_cli(a->fd, "name: %s\ntype: dialog\nobjflags: %d\nrefcount: %d\n\n",
pvt->callid, 0, refc);
return 0;
@@ -19448,7 +19472,7 @@
static char *sip_show_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char tmp[256];
-
+
switch (cmd) {
case CLI_INIT:
e->command = "sip show objects";
@@ -19458,13 +19482,13 @@
return NULL;
case CLI_GENERATE:
return NULL;
- }
+ }
if (a->argc != 3)
return CLI_SHOWUSAGE;
ast_cli(a->fd, "-= Peer objects: %d static, %d realtime, %d autocreate =-\n\n", speerobjs, rpeerobjs, apeerobjs);
ao2_t_callback(peers, OBJ_NODATA, peer_dump_func, a, "initiate ao2_callback to dump peers");
- ast_cli(a->fd, "-= Peer objects by IP =-\n\n");
+ ast_cli(a->fd, "-= Peer objects by IP =-\n\n");
ao2_t_callback(peers_by_ip, OBJ_NODATA, peer_dump_func, a, "initiate ao2_callback to dump peers_by_ip");
ast_cli(a->fd, "-= Registry objects: %d =-\n\n", regobjs);
ASTOBJ_CONTAINER_DUMP(a->fd, tmp, sizeof(tmp), ®l);
@@ -19557,7 +19581,7 @@
} else if (strcmp(newcontext, oldcontext)) {
stalecontext = oldcontext;
}
-
+
}
if (stalecontext)
ast_context_destroy(ast_context_find(stalecontext), "SIP");
@@ -19655,7 +19679,7 @@
struct ao2_iterator i;
static const char * const choices[] = { "all", "like", NULL };
char *cmplt;
-
+
if (cmd == CLI_INIT) {
e->command = "sip prune realtime [peer|all]";
e->usage =
@@ -19729,7 +19753,7 @@
if (multi) {
if (prunepeer) {
int pruned = 0;
-
+
i = ao2_iterator_init(peers, 0);
while ((pi = ao2_t_iterator_next(&i, "iterate thru peers table"))) {
ao2_lock(pi);
@@ -20548,7 +20572,7 @@
sip_poke_noanswer,
sip_reregister,
sip_reinvite_retry}};
-
+
switch (cmd) {
case CLI_INIT:
e->command = "sip show sched";
@@ -20594,7 +20618,7 @@
if (a->argc != 3)
return CLI_SHOWUSAGE;
ast_cli(a->fd, FORMAT2, "Host", "dnsmgr", "Username", "Refresh", "State", "Reg.Time");
-
+
ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do {
ASTOBJ_RDLOCK(iterator);
snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT);
@@ -20639,10 +20663,10 @@
case CLI_GENERATE:
return complete_sip_unregister(a->line, a->word, a->pos, a->n);
}
-
+
if (a->argc != 3)
return CLI_SHOWUSAGE;
-
+
if ((peer = sip_find_peer(a->argv[2], NULL, load_realtime, FINDPEERS, TRUE, 0))) {
if (peer->expire > 0) {
AST_SCHED_DEL_UNREF(sched, peer->expire,
@@ -20656,7 +20680,7 @@
} else {
ast_cli(a->fd, "Peer unknown: \'%s\'. Not unregistered.\n", a->argv[2]);
}
-
+
return CLI_SUCCESS;
}
@@ -20983,7 +21007,7 @@
ast_cli(a->fd, " MOH Suggest: %s\n", default_mohsuggest);
ast_cli(a->fd, " Voice Mail Extension: %s\n", default_vmexten);
-
+
if (realtimepeers || realtimeregs) {
ast_cli(a->fd, "\nRealtime SIP Settings:\n");
ast_cli(a->fd, "----------------------\n");
@@ -21004,7 +21028,7 @@
{
#define FORMAT "%-30.30s %-12.12s %-10.10s %-10.10s\n"
char host[80];
-
+
switch (cmd) {
case CLI_INIT:
e->command = "sip show mwi";
@@ -21015,9 +21039,9 @@
case CLI_GENERATE:
return NULL;
}
-
+
ast_cli(a->fd, FORMAT, "Host", "Username", "Mailbox", "Subscribed");
-
+
ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do {
ASTOBJ_RDLOCK(iterator);
snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT);
@@ -21083,7 +21107,7 @@
/* set if SIP transfer in progress */
const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : "";
char formatbuf[SIPBUFSIZE/2];
-
+
ast_cli(arg->fd, FORMAT, ast_sockaddr_stringify_addr(dst),
S_OR(cur->username, S_OR(cur->cid_num, "(None)")),
cur->callid,
@@ -21147,7 +21171,7 @@
/* iterate on the container and invoke the callback on each item */
ao2_t_callback(dialogs, OBJ_NODATA, show_channels_cb, &arg, "callback to show channels");
-
+
/* print summary information */
ast_cli(arg.fd, "%d active SIP %s%s\n", arg.numchans,
(arg.subscriptions ? "subscription" : "dialog"),
@@ -21224,7 +21248,7 @@
int which = 0;
struct ao2_iterator i;
struct sip_peer *peer;
-
+
i = ao2_iterator_init(peers, 0);
while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) {
if (!strncasecmp(word, peer->name, wordlen) &&
@@ -21283,7 +21307,7 @@
if (!notify_types)
return NULL;
-
+
while ( (cat = ast_category_browse(notify_types, cat)) ) {
if (!strncasecmp(word, cat, wordlen) && ++which > state) {
c = ast_strdup(cat);
@@ -21321,7 +21345,7 @@
if (a->argc != 4)
return CLI_SHOWUSAGE;
len = strlen(a->argv[3]);
-
+
i = ao2_iterator_init(dialogs, 0);
while ((cur = ao2_t_iterator_next(&i, "iterate thru dialogs"))) {
sip_pvt_lock(cur);
@@ -22097,7 +22121,7 @@
} else {
/* No authentication, use peer or register= config */
username = p->authname;
- secret = p->relatedpeer
+ secret = p->relatedpeer
&& !ast_strlen_zero(p->relatedpeer->remotesecret)
? p->relatedpeer->remotesecret : p->peersecret;
md5secret = p->peermd5secret;
@@ -22144,7 +22168,7 @@
}
return 0;
}
-
+
/*! \brief Read SIP header (dialplan function) */
static int func_header_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
{
@@ -22341,7 +22365,7 @@
static int deprecated = 0;
*buf = 0;
-
+
if (!data) {
ast_log(LOG_WARNING, "This function requires a parameter name.\n");
return -1;
@@ -22593,7 +22617,7 @@
}
}
-/*! \brief Check pending actions on SIP call
+/*! \brief Check pending actions on SIP call
*
* \note both sip_pvt and sip_pvt's owner channel (if present)
* must be locked for this function.
@@ -22866,7 +22890,7 @@
if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA )) {
p->invitestate = INV_COMPLETED;
}
-
+
if ((resp >= 200 && reinvite)) {
p->ongoing_reinvite = 0;
if (p->reinviteid > -1) {
@@ -23107,7 +23131,7 @@
/* Bad contact - we don't know how to reach this device */
/* We need to ACK, but then send a bye */
if (!p->route && !req->ignore) {
- ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
+ ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
}
}
@@ -23133,7 +23157,7 @@
by sending CANCEL */
/* First send ACK, then send bye */
if (!req->ignore) {
- ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
+ ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
}
}
@@ -23146,7 +23170,7 @@
int tmp_st_interval = 0;
rtn = parse_session_expires(p_hdrval, &tmp_st_interval, &st_ref_param);
if (rtn != 0) {
- ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
+ ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
} else if (tmp_st_interval < st_get_se(p, FALSE)) {
ast_log(LOG_WARNING, "Got Session-Expires less than local Min-SE in 200 OK, tearing down call\n");
ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
@@ -23519,7 +23543,7 @@
pvt_set_needdestroy(p, "failed to authenticate REFER");
}
break;
-
+
case 405: /* Method not allowed */
/* Return to the current call onhold */
/* Status flag needed to be reset */
@@ -23563,7 +23587,7 @@
break;
default:
/* We should treat unrecognized 9xx as 900. 400 is actually
- specified as a possible response, but any 4-6xx is
+ specified as a possible response, but any 4-6xx is
theoretically possible. */
if (resp < 299) { /* 1xx cases don't get here */
@@ -23587,7 +23611,7 @@
int expires, expires_ms;
struct sip_registry *r;
r = p->registry;
-
+
switch (resp) {
case 401: /* Unauthorized */
if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) {
@@ -23699,13 +23723,13 @@
if (sscanf(tmptmp + 8, "%30d;", &expires) != 1)
expires = 0;
}
-
+
}
if (!expires)
expires=atoi(sip_get_header(req, "expires"));
if (!expires)
expires=default_expiry;
-
+
expires_ms = expires * 1000;
if (expires <= EXPIRY_GUARD_LIMIT)
expires_ms -= MAX((expires_ms * EXPIRY_GUARD_PCT), EXPIRY_GUARD_MIN);
@@ -23713,9 +23737,9 @@
expires_ms -= EXPIRY_GUARD_SECS * 1000;
if (sipdebug)
ast_log(LOG_NOTICE, "Outbound Registration: Expiry for %s is %d sec (Scheduling reregistration in %d s)\n", r->hostname, expires, expires_ms/1000);
-
+
r->refresh= (int) expires_ms / 1000;
-
+
/* Schedule re-registration before we expire */
AST_SCHED_REPLACE_UNREF(r->expire, sched, expires_ms, sip_reregister, r,
registry_unref(_data,"unref in REPLACE del fail"),
@@ -24206,7 +24230,7 @@
/* Fatal response */
if ((resp != 487))
ast_verb(3, "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_sockaddr_stringify(&p->sa));
-
+
if (sipmethod == SIP_INVITE)
stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */
@@ -24266,7 +24290,7 @@
}
break;
default:
- /* Send hangup */
+ /* Send hangup */
if (owner && sipmethod != SIP_BYE)
ast_queue_hangup_with_cause(p->owner, hangup_sip2cause(resp));
break;
@@ -24292,7 +24316,7 @@
} else
ast_log(LOG_NOTICE, "Don't know how to handle a %d %s response from %s\n", resp, rest, p->owner ? ast_channel_name(p->owner) : ast_sockaddr_stringify(&p->sa));
}
- } else {
+ } else {
/* Responses to OUTGOING SIP requests on INCOMING calls
get handled here. As well as out-of-call message responses */
if (req->debug)
@@ -24786,7 +24810,7 @@
A minimal, but complete, implementation can respond with a single
NOTIFY containing either the body:
SIP/2.0 100 Trying
-
+
if the subscription is pending, the body:
SIP/2.0 200 OK
if the reference was successful, the body:
@@ -24797,7 +24821,7 @@
if the REFER request was accepted before approval to follow the
[... 266 lines stripped ...]
More information about the asterisk-commits
mailing list