Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:00:56 2007

Asterisk developer's documentation :: Codename Pineapple


sip3_cliami.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 SIP CLI and manager commands
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/cli.h"
00057 #include "asterisk/lock.h"
00058 #include "asterisk/channel.h"
00059 #include "asterisk/config.h"
00060 #include "asterisk/logger.h"
00061 #include "asterisk/module.h"
00062 #include "asterisk/pbx.h"
00063 #include "asterisk/options.h"
00064 #include "asterisk/sched.h"
00065 #include "asterisk/io.h"
00066 #include "asterisk/rtp.h"
00067 #include "asterisk/udptl.h"
00068 #include "asterisk/acl.h"
00069 #include "asterisk/manager.h"
00070 #include "asterisk/callerid.h"
00071 #include "asterisk/cli.h"
00072 #include "asterisk/app.h"
00073 #include "asterisk/musiconhold.h"
00074 #include "asterisk/features.h"
00075 //#include "asterisk/srv.h"
00076 //#include "asterisk/astdb.h"
00077 #include "asterisk/causes.h"
00078 #include "asterisk/utils.h"
00079 #include "asterisk/file.h"
00080 #include "asterisk/astobj.h"
00081 #include "asterisk/dnsmgr.h"
00082 #include "asterisk/devicestate.h"
00083 #include "asterisk/linkedlists.h"
00084 #include "asterisk/stringfields.h"
00085 #include "asterisk/monitor.h"
00086 #include "asterisk/localtime.h"
00087 #include "asterisk/abstract_jb.h"
00088 #include "asterisk/compiler.h"
00089 #include "sip3.h"
00090 #include "sip3funcs.h"
00091 
00092 
00093 /*! \brief Display SIP nat mode */
00094 const char *sip_nat_mode(const struct sip_dialog *p)
00095 {
00096    return ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE ? "NAT" : "no NAT";
00097 }
00098 
00099 /*! \brief Convert transfer mode to text string */
00100 static char *transfermode2str(enum transfermodes mode)
00101 {
00102    if (mode == TRANSFER_OPENFORALL)
00103       return "open";
00104    else if (mode == TRANSFER_CLOSED)
00105       return "closed";
00106    return "strict";
00107 }
00108 
00109 /*! \brief  Convert NAT setting to text string */
00110 static char *nat2str(int nat)
00111 {
00112    switch(nat) {
00113    case SIP_NAT_NEVER:
00114       return "No";
00115    case SIP_NAT_ROUTE:
00116       return "Route";
00117    case SIP_NAT_ALWAYS:
00118       return "Always";
00119    case SIP_NAT_RFC3581:
00120       return "RFC3581";
00121    default:
00122       return "Unknown";
00123    }
00124 }
00125 
00126 /*! \brief Convert DTMF mode to printable string */
00127 static const char *dtmfmode2str(int mode)
00128 {
00129    switch (mode) {
00130    case SIP_DTMF_RFC2833:
00131       return "rfc2833";
00132    case SIP_DTMF_INFO:
00133       return "info";
00134    case SIP_DTMF_INBAND:
00135       return "inband";
00136    case SIP_DTMF_AUTO:
00137       return "auto";
00138    }
00139    return "<error>";
00140 }
00141 
00142 /*! \brief Convert Insecure setting to printable string */
00143 static const char *insecure2str(int port, int invite)
00144 {
00145    if (port && invite)
00146       return "port,invite";
00147    else if (port)
00148       return "port";
00149    else if (invite)
00150       return "invite";
00151    else
00152       return "no";
00153 }
00154 
00155 /*! \brief Print codec list from preference to CLI/manager */
00156 static void print_codec_to_cli(int fd, struct ast_codec_pref *pref)
00157 {
00158    int x, codec;
00159 
00160    for(x = 0; x < 32 ; x++) {
00161       codec = ast_codec_pref_index(pref, x);
00162       if (!codec)
00163          break;
00164       ast_cli(fd, "%s", ast_getformatname(codec));
00165       ast_cli(fd, ":%d", pref->framing[x]);
00166       if (x < 31 && ast_codec_pref_index(pref, x + 1))
00167          ast_cli(fd, ",");
00168    }
00169    if (!x)
00170       ast_cli(fd, "none");
00171 }
00172 
00173 /*! \brief Print call group and pickup group */
00174 void  print_group(int fd, ast_group_t group, int crlf)
00175 {
00176    char buf[256];
00177    ast_cli(fd, crlf ? "%s\r\n" : "%s\n", ast_print_group(buf, sizeof(buf), group) );
00178 }
00179 
00180 /*! \brief  Report Device status in character string
00181  *  \return 0 if peer is unreachable, 1 if peer is online, -1 if unmonitored
00182  */
00183 int device_status(struct sip_device *device, char *status, int statuslen)
00184 {
00185    int res = 0;
00186    if (device->maxms) {
00187       if (device->lastms < 0) {
00188          ast_copy_string(status, "UNREACHABLE", statuslen);
00189       } else if (device->lastms > device->maxms) {
00190          snprintf(status, statuslen, "LAGGED (%d ms)", device->lastms);
00191          res = 1;
00192       } else if (device->lastms) {
00193          snprintf(status, statuslen, "OK (%d ms)", device->lastms);
00194          res = 1;
00195       } else {
00196          ast_copy_string(status, "UNKNOWN", statuslen);
00197       }
00198    } else { 
00199       ast_copy_string(status, "Unmonitored", statuslen);
00200       /* Checking if port is 0 */
00201       res = -1;
00202    }
00203    return res;
00204 }
00205 
00206 /*! \brief  CLI Command to show calls within limits set by call_limit */
00207 static int sip_show_inuse(int fd, int argc, char *argv[])
00208 {
00209 #define FORMAT  "%-25.25s %-15.15s %-15.15s \n"
00210 #define FORMAT2 "%-25.25s %-15.15s %-15.15s \n"
00211    char ilimits[40];
00212    char iused[40];
00213    int showall = FALSE;
00214 
00215    if (argc < 3) 
00216       return RESULT_SHOWUSAGE;
00217 
00218    if (argc == 4 && !strcmp(argv[3],"all")) 
00219          showall = TRUE;
00220    
00221    ast_cli(fd, FORMAT, "* Peer name", "In use", "Limit");
00222 
00223    ASTOBJ_CONTAINER_TRAVERSE(&devicelist, 1, do {
00224       ASTOBJ_RDLOCK(iterator);
00225       if (iterator->call_limit)
00226          snprintf(ilimits, sizeof(ilimits), "%d", iterator->call_limit);
00227       else 
00228          ast_copy_string(ilimits, "N/A", sizeof(ilimits));
00229       snprintf(iused, sizeof(iused), "%d/%d", iterator->inUse, iterator->inRinging);
00230       if (showall || iterator->call_limit)
00231          ast_cli(fd, FORMAT2, iterator->name, iused, ilimits);
00232       ASTOBJ_UNLOCK(iterator);
00233    } while (0) );
00234 
00235    return RESULT_SUCCESS;
00236 #undef FORMAT
00237 #undef FORMAT2
00238 }
00239 
00240 char mandescr_show_devices[] = 
00241 "Description: Lists SIP peers in text format with details on current status.\n"
00242 "Variables: \n"
00243 "  ActionID: <id> Action ID for this transaction. Will be returned.\n";
00244 
00245 /*! \brief  Execute sip show devices command */
00246 static int _sip_show_devices(int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[])
00247 {
00248    regex_t regexbuf;
00249    int havepattern = FALSE;
00250 
00251 #define FORMAT2 "%-25.25s  %-15.15s %-3.3s %-3.3s %-3.3s %-8s %-10s %-10s\n"
00252 #define FORMAT  "%-25.25s  %-15.15s %-3.3s %-3.3s %-3.3s %-8d %-10s %-10s\n"
00253 
00254    char name[256];
00255    int total_peers = 0;
00256    int peers_mon_online = 0;
00257    int peers_mon_offline = 0;
00258    int peers_unmon_offline = 0;
00259    int peers_unmon_online = 0;
00260    const char *id;
00261    char idtext[256] = "";
00262    int realtimepeers;
00263 
00264    realtimepeers = ast_check_realtime("sippeers");
00265 
00266    if (s) { /* Manager - get ActionID */
00267       id = astman_get_header(m, "ActionID");
00268       if (!ast_strlen_zero(id))
00269          snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
00270    }
00271 
00272    switch (argc) {
00273    case 5:
00274       if (!strcasecmp(argv[3], "like")) {
00275          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
00276             return RESULT_SHOWUSAGE;
00277          havepattern = TRUE;
00278       } else
00279          return RESULT_SHOWUSAGE;
00280    case 3:
00281       break;
00282    default:
00283       return RESULT_SHOWUSAGE;
00284    }
00285 
00286    if (!s) /* Normal list */
00287       ast_cli(fd, FORMAT2, "Name", "Host", "Dyn", "Nat", "ACL", "Port", "Status", (realtimepeers ? "Realtime" : ""));
00288    
00289    ASTOBJ_CONTAINER_TRAVERSE(&devicelist, 1, do {
00290       char status[20] = "";
00291       char srch[2000];
00292       char pstatus;
00293       
00294       ASTOBJ_RDLOCK(iterator);
00295 
00296       if (havepattern && regexec(&regexbuf, iterator->name, 0, NULL, 0)) {
00297          ASTOBJ_UNLOCK(iterator);
00298          continue;
00299       }
00300 
00301       if (!ast_strlen_zero(iterator->domain) && !s)
00302          snprintf(name, sizeof(name), "%s@%s", iterator->name, iterator->domain);
00303       else
00304          ast_copy_string(name, iterator->name, sizeof(name));
00305       
00306       pstatus = device_status(iterator, status, sizeof(status));
00307       if (pstatus == 1)
00308          peers_mon_online++;
00309       else if (pstatus == 0)
00310          peers_mon_offline++;
00311       else {
00312          if (iterator->addr.sin_port == 0)
00313             peers_unmon_offline++;
00314          else
00315             peers_unmon_online++;
00316       }
00317 
00318       snprintf(srch, sizeof(srch), FORMAT, name,
00319          iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iterator->addr.sin_addr) : "(Unspecified)",
00320          ast_test_flag(&iterator->flags[1], SIP_PAGE2_DYNAMIC) ? " D " : "   ",  /* Dynamic or not? */
00321          ast_test_flag(&iterator->flags[0], SIP_NAT_ROUTE) ? " N " : "   ",   /* NAT=yes? */
00322          iterator->ha ? " A " : "   ",    /* permit/deny */
00323          ntohs(iterator->addr.sin_port), status,
00324          realtimepeers ? (ast_test_flag(&iterator->flags[0], SIP_REALTIME) ? "Cached RT":"") : "");
00325 
00326       if (!s)  {/* Normal CLI list */
00327          ast_cli(fd, FORMAT, name, 
00328          iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iterator->addr.sin_addr) : "(Unspecified)",
00329          ast_test_flag(&iterator->flags[1], SIP_PAGE2_DYNAMIC) ? " D " : "   ",  /* Dynamic or not? */
00330          ast_test_flag(&iterator->flags[0], SIP_NAT_ROUTE) ? " N " : "   ",   /* NAT=yes? */
00331          iterator->ha ? " A " : "   ",       /* permit/deny */
00332          
00333          ntohs(iterator->addr.sin_port), status,
00334          realtimepeers ? (ast_test_flag(&iterator->flags[0], SIP_REALTIME) ? "Cached RT":"") : "");
00335       } else { /* Manager format */
00336          /* The names here need to be the same as other channels */
00337          astman_append(s, 
00338          "Event: PeerEntry\r\n%s"
00339          "Channeltype: SIP\r\n"
00340          "ObjectName: %s\r\n"
00341          "ChanObjectType: peer\r\n" /* "peer" or "user" */
00342          "IPaddress: %s\r\n"
00343          "IPport: %d\r\n"
00344          "Dynamic: %s\r\n"
00345          "Natsupport: %s\r\n"
00346          "VideoSupport: %s\r\n"
00347          "ACL: %s\r\n"
00348          "Status: %s\r\n"
00349          "RealtimeDevice: %s\r\n\r\n", 
00350          idtext,
00351          iterator->name, 
00352          iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iterator->addr.sin_addr) : "-none-",
00353          ntohs(iterator->addr.sin_port), 
00354          ast_test_flag(&iterator->flags[1], SIP_PAGE2_DYNAMIC) ? "yes" : "no",   /* Dynamic or not? */
00355          ast_test_flag(&iterator->flags[0], SIP_NAT_ROUTE) ? "yes" : "no", /* NAT=yes? */
00356          ast_test_flag(&iterator->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no", /* VIDEOSUPPORT=yes? */
00357          iterator->ha ? "yes" : "no",       /* permit/deny */
00358          status,
00359          realtimepeers ? (ast_test_flag(&iterator->flags[0], SIP_REALTIME) ? "yes":"no") : "no");
00360       }
00361 
00362       ASTOBJ_UNLOCK(iterator);
00363 
00364       total_peers++;
00365    } while(0) );
00366    
00367    if (!s)
00368       ast_cli(fd, "%d sip peers [Monitored: %d online, %d offline Unmonitored: %d online, %d offline]\n",
00369               total_peers, peers_mon_online, peers_mon_offline, peers_unmon_online, peers_unmon_offline);
00370 
00371    if (havepattern)
00372       regfree(&regexbuf);
00373 
00374    if (total)
00375       *total = total_peers;
00376    
00377 
00378    return RESULT_SUCCESS;
00379 #undef FORMAT
00380 #undef FORMAT2
00381 }
00382 
00383 /*! \brief  Show SIP peers in the manager API */
00384 /*    Inspired from chan_iax2 */
00385 int manager_sip_show_devices(struct mansession *s, const struct message *m )
00386 {
00387    const char *id = astman_get_header(m,"ActionID");
00388    const char *a[] = { "sip3", "show", "peers" };
00389    char idtext[256] = "";
00390    int total = 0;
00391 
00392    if (!ast_strlen_zero(id))
00393       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
00394 
00395    astman_send_ack(s, m, "Peer status list will follow");
00396    /* List the peers in separate manager events */
00397    _sip_show_devices(-1, &total, s, m, 3, a);
00398    /* Send final confirmation */
00399    astman_append(s,
00400    "Event: PeerlistComplete\r\n"
00401    "ListItems: %d\r\n"
00402    "%s"
00403    "\r\n", total, idtext);
00404    return 0;
00405 }
00406 
00407 
00408 /*! \brief  CLI Show Peers command */
00409 static int sip_show_devices(int fd, int argc, char *argv[])
00410 {
00411    return _sip_show_devices(fd, NULL, NULL, NULL, argc, (const char **) argv);
00412 }
00413 
00414 
00415 /*! \brief List all allocated SIP Objects (realtime or static) */
00416 static int sip_show_objects(int fd, int argc, char *argv[])
00417 {
00418    char tmp[256];
00419    if (argc != 3)
00420       return RESULT_SHOWUSAGE;
00421    ast_cli(fd, "-= Device objects: %d static, %d realtime, %d autocreate =-\n\n", sipcounters.static_peers, sipcounters.realtime_peers, sipcounters.autocreated_peers);
00422    ASTOBJ_CONTAINER_DUMP(fd, tmp, sizeof(tmp), &devicelist);
00423    ast_cli(fd, "-= Registry objects: %d =-\n\n", sipcounters.registry_objects);
00424    ast_cli(fd, "-= Dialog objects: %d =-\n\n", sipcounters.dialog_objects);
00425    ASTOBJ_CONTAINER_DUMP(fd, tmp, sizeof(tmp), &regl);
00426    return RESULT_SUCCESS;
00427 }
00428 
00429 static char mandescr_show_device[] = 
00430 "Description: Show one SIP device with details on current status.\n"
00431 "Variables: \n"
00432 "  Peer: <name>           The peer name you want to check.\n"
00433 "  ActionID: <id>   Optional action ID for this AMI transaction.\n";
00434 
00435 /*! \brief Show one peer in detail (main function) */
00436 static int _sip_show_device(int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[])
00437 {
00438    char status[30] = "";
00439    char cbuf[256];
00440    struct sip_device *device;
00441    char codec_buf[512];
00442    struct ast_codec_pref *pref;
00443    struct ast_variable *v;
00444    struct sip_auth *auth;
00445    int x = 0, codec = 0, load_realtime;
00446    int realtimepeers;
00447 
00448    realtimepeers = ast_check_realtime("sippeers");
00449 
00450    if (argc < 4)
00451       return RESULT_SHOWUSAGE;
00452 
00453    load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE;
00454    device = find_device(argv[3], NULL, load_realtime);
00455    if (s) {    /* Manager */
00456       if (device)
00457          astman_append(s, "Response: Success\r\n");
00458       else {
00459          snprintf (cbuf, sizeof(cbuf), "Device %s not found.\n", argv[3]);
00460          astman_send_error(s, m, cbuf);
00461          return 0;
00462       }
00463    }
00464    if (device && type==0 ) { /* Normal listing */
00465       ast_cli(fd,"\n\n");
00466       if (!ast_strlen_zero(device->domain))
00467          ast_cli(fd, "  * Name       : %s@%s\n", device->name, device->domain);
00468       else
00469          ast_cli(fd, "  * Name       : %s <no domain>\n", device->name);
00470       if (realtimepeers) { /* Realtime is enabled */
00471          ast_cli(fd, "  Realtime device: %s\n", ast_test_flag(&device->flags[0], SIP_REALTIME) ? "Yes, cached" : "No");
00472       }
00473       ast_cli(fd, "  Secret       : %s\n", ast_strlen_zero(device->secret)?"<Not set>":"<Set>");
00474       ast_cli(fd, "  MD5Secret    : %s\n", ast_strlen_zero(device->md5secret)?"<Not set>":"<Set>");
00475       for (auth = device->auth; auth; auth = auth->next) {
00476          ast_cli(fd, "  Realm-auth   : Realm %-15.15s User %-10.20s ", auth->realm, auth->username);
00477          ast_cli(fd, "%s\n", !ast_strlen_zero(auth->secret)?"<Secret set>":(!ast_strlen_zero(auth->md5secret)?"<MD5secret set>" : "<Not set>"));
00478       }
00479       ast_cli(fd, "  Context      : %s\n", device->extra.context);
00480       ast_cli(fd, "  Subscr.Cont. : %s\n", S_OR(device->extra.subscribecontext, "<Not set>") );
00481       ast_cli(fd, "  Language     : %s\n", device->language);
00482       if (!ast_strlen_zero(device->extra.accountcode))
00483          ast_cli(fd, "  Accountcode  : %s\n", device->extra.accountcode);
00484       ast_cli(fd, "  AMA flags    : %s\n", ast_cdr_flags2str(device->extra.amaflags));
00485       ast_cli(fd, "  Transfer mode: %s\n", transfermode2str(device->allowtransfer));
00486       ast_cli(fd, "  CallingPres  : %s\n", ast_describe_caller_presentation(device->callingpres));
00487       if (!ast_strlen_zero(device->extra.fromuser))
00488          ast_cli(fd, "  FromUser     : %s\n", device->extra.fromuser);
00489       if (!ast_strlen_zero(device->extra.fromdomain))
00490          ast_cli(fd, "  FromDomain   : %s\n", device->extra.fromdomain);
00491       ast_cli(fd, "  Callgroup    : ");
00492       print_group(fd, device->callgroup, 0);
00493       ast_cli(fd, "  Pickupgroup  : ");
00494       print_group(fd, device->pickupgroup, 0);
00495       ast_cli(fd, "  Mailbox      : %s\n", device->mailbox.mailbox);
00496       ast_cli(fd, "  VM Extension : %s\n", device->mailbox.vmexten);
00497       ast_cli(fd, "  Call limit   : %d\n", device->call_limit);
00498       ast_cli(fd, "  Dynamic      : %s\n", (ast_test_flag(&device->flags[1], SIP_PAGE2_DYNAMIC)?"Yes":"No"));
00499       ast_cli(fd, "  Expire       : %ld\n", ast_sched_when(sched, device->expire));
00500       ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), device->extra.cid_name, device->extra.cid_num, "<unspecified>"));
00501       if (!ast_strlen_zero(global.regcontext))
00502          ast_cli(fd, "  Reg. exten   : %s\n", device->extra.regexten);
00503       ast_cli(fd, "  MaxCallBR    : %d kbps\n", device->maxcallbitrate);
00504       ast_cli(fd, "  Insecure     : %s\n", insecure2str(ast_test_flag(&device->flags[0], SIP_INSECURE_PORT), ast_test_flag(&device->flags[0], SIP_INSECURE_INVITE)));
00505       ast_cli(fd, "  Nat support  : %s\n", nat2str(ast_test_flag(&device->flags[0], SIP_NAT)));
00506       ast_cli(fd, "  CanReinvite  : %s\n", ast_test_flag(&device->flags[0], SIP_CAN_REINVITE)?"Yes":"No");
00507       ast_cli(fd, "  ACL          : %s\n", (device->ha?"Yes":"No"));
00508       ast_cli(fd, "  T38 pt UDPTL : %s\n", ast_test_flag(&device->flags[1], SIP_PAGE2_T38SUPPORT_UDPTL)?"Yes":"No");
00509       ast_cli(fd, "  T38 pt RTP   : %s\n", ast_test_flag(&device->flags[1], SIP_PAGE2_T38SUPPORT_RTP)?"Yes":"No");
00510       ast_cli(fd, "  T38 pt TCP   : %s\n", ast_test_flag(&device->flags[1], SIP_PAGE2_T38SUPPORT_TCP)?"Yes":"No");
00511       ast_cli(fd, "  PromiscRedir : %s\n", ast_test_flag(&device->flags[0], SIP_PROMISCREDIR)?"Yes":"No");
00512       ast_cli(fd, "  Video Support: %s\n", ast_test_flag(&device->flags[1], SIP_PAGE2_VIDEOSUPPORT)?"Yes":"No");
00513       ast_cli(fd, "  Trust RPID   : %s\n", ast_test_flag(&device->flags[0], SIP_TRUSTRPID) ? "Yes" : "No");
00514       ast_cli(fd, "  Send RPID    : %s\n", ast_test_flag(&device->flags[0], SIP_SENDRPID) ? "Yes" : "No");
00515       ast_cli(fd, "  Subscriptions: %s\n", ast_test_flag(&device->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE) ? "Yes" : "No");
00516       ast_cli(fd, "  Overlap dial : %s\n", ast_test_flag(&device->flags[1], SIP_PAGE2_ALLOWOVERLAP) ? "Yes" : "No");
00517 
00518       /* - is enumerated */
00519       ast_cli(fd, "  DTMFmode     : %s\n", dtmfmode2str(ast_test_flag(&device->flags[0], SIP_DTMF)));
00520       ast_cli(fd, "  User=Phone   : %s\n", ast_test_flag(&device->flags[0], SIP_USEREQPHONE)?"Yes":"No");
00521       ast_cli(fd, "  ToHost       : %s\n", device->extra.tohost);
00522       ast_cli(fd, "  Addr->IP     : %s Port %d\n",  device->addr.sin_addr.s_addr ? ast_inet_ntoa(device->addr.sin_addr) : "(Unspecified)", ntohs(device->addr.sin_port));
00523       ast_cli(fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(device->defaddr.sin_addr), ntohs(device->defaddr.sin_port));
00524       ast_cli(fd, "  Def. Username: %s\n", device->defaultuser);
00525       ast_cli(fd, "  Codecs       : ");
00526       ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, device->capability);
00527       ast_cli(fd, "%s\n", codec_buf);
00528       ast_cli(fd, "  Codec Order  : (");
00529       print_codec_to_cli(fd, &device->prefs);
00530       ast_cli(fd, ")\n");
00531 
00532       ast_cli(fd, "  LastMsgsSent : %d\n", device->mailbox.lastmsgssent);
00533       ast_cli(fd, "  SIP Options  : ");
00534       if (device->sipoptions) {
00535          sip_options_print(device->sipoptions, fd);
00536       } else
00537          ast_cli(fd, "(none)");
00538       ast_cli(fd, "\n");
00539 
00540       device_status(device, status, sizeof(status));
00541       ast_cli(fd, "  Status       : %s\n", status);
00542       ast_cli(fd, "  Useragent    : %s\n", device->useragent);
00543       ast_cli(fd, "  Reg. Contact : %s\n", device->fullcontact);
00544       if (device->chanvars) {
00545          ast_cli(fd, "  Variables    :\n");
00546          for (v = device->chanvars ; v ; v = v->next)
00547             ast_cli(fd, "                 %s = %s\n", v->name, v->value);
00548       }
00549       ast_cli(fd,"\n");
00550       device_unref(device);
00551    } else  if (device && type == 1) { /* manager listing */
00552       char buf[256];
00553       astman_append(s, "Channeltype: SIP\r\n");
00554       astman_append(s, "ObjectName: %s\r\n", device->name);
00555       astman_append(s, "SIPDomain: %s\r\n", device->domain);
00556       astman_append(s, "ChanObjectType: device\r\n");
00557       astman_append(s, "SecretExist: %s\r\n", ast_strlen_zero(device->secret)?"N":"Y");
00558       astman_append(s, "MD5SecretExist: %s\r\n", ast_strlen_zero(device->md5secret)?"N":"Y");
00559       astman_append(s, "Context: %s\r\n", device->extra.context);
00560       astman_append(s, "Language: %s\r\n", device->language);
00561       if (!ast_strlen_zero(device->extra.accountcode))
00562          astman_append(s, "Accountcode: %s\r\n", device->extra.accountcode);
00563       astman_append(s, "AMAflags: %s\r\n", ast_cdr_flags2str(device->extra.amaflags));
00564       astman_append(s, "CID-CallingPres: %s\r\n", ast_describe_caller_presentation(device->callingpres));
00565       if (!ast_strlen_zero(device->extra.fromuser))
00566          astman_append(s, "SIP-FromUser: %s\r\n", device->extra.fromuser);
00567       if (!ast_strlen_zero(device->extra.fromdomain))
00568          astman_append(s, "SIP-FromDomain: %s\r\n", device->extra.fromdomain);
00569       astman_append(s, "Callgroup: ");
00570       astman_append(s, "%s\r\n", ast_print_group(buf, sizeof(buf), device->callgroup));
00571       astman_append(s, "Pickupgroup: ");
00572       astman_append(s, "%s\r\n", ast_print_group(buf, sizeof(buf), device->pickupgroup));
00573       astman_append(s, "VoiceMailbox: %s\r\n", device->mailbox.mailbox);
00574       astman_append(s, "TransferMode: %s\r\n", transfermode2str(device->allowtransfer));
00575       astman_append(s, "LastMsgsSent: %d\r\n", device->mailbox.lastmsgssent);
00576       astman_append(s, "Call limit: %d\r\n", device->call_limit);
00577       astman_append(s, "MaxCallBR: %d kbps\r\n", device->maxcallbitrate);
00578       astman_append(s, "Dynamic: %s\r\n", (ast_test_flag(&device->flags[1], SIP_PAGE2_DYNAMIC)?"Y":"N"));
00579       astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), device->extra.cid_name, device->extra.cid_num, ""));
00580       astman_append(s, "RegExpire: %ld seconds\r\n", ast_sched_when(sched,device->expire));
00581       astman_append(s, "SIP-AuthInsecure: %s\r\n", insecure2str(ast_test_flag(&device->flags[0], SIP_INSECURE_PORT), ast_test_flag(&device->flags[0], SIP_INSECURE_INVITE)));
00582       astman_append(s, "SIP-NatSupport: %s\r\n", nat2str(ast_test_flag(&device->flags[0], SIP_NAT)));
00583       astman_append(s, "ACL: %s\r\n", (device->ha?"Y":"N"));
00584       astman_append(s, "SIP-CanReinvite: %s\r\n", (ast_test_flag(&device->flags[0], SIP_CAN_REINVITE)?"Y":"N"));
00585       astman_append(s, "SIP-PromiscRedir: %s\r\n", (ast_test_flag(&device->flags[0], SIP_PROMISCREDIR)?"Y":"N"));
00586       astman_append(s, "SIP-UserPhone: %s\r\n", (ast_test_flag(&device->flags[0], SIP_USEREQPHONE)?"Y":"N"));
00587       astman_append(s, "SIP-VideoSupport: %s\r\n", (ast_test_flag(&device->flags[1], SIP_PAGE2_VIDEOSUPPORT)?"Y":"N"));
00588       astman_append(s, "T38pt-UDPTL: %s\n", ast_test_flag(&device->flags[1], SIP_PAGE2_T38SUPPORT_UDPTL)?"Y":"N");
00589       astman_append(s, "T38pt-RTP: %s\n", ast_test_flag(&device->flags[1], SIP_PAGE2_T38SUPPORT_RTP)?"Y":"N");
00590       astman_append(s, "T38pt-TCP: %s\n", ast_test_flag(&device->flags[1], SIP_PAGE2_T38SUPPORT_TCP)?"Y":"N");
00591 
00592       /* - is enumerated */
00593       astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&device->flags[0], SIP_DTMF)));
00594       astman_append(s, "ToHost: %s\r\n", device->extra.tohost);
00595       astman_append(s, "Address-IP: %s\r\nAddress-Port: %d\r\n",  device->addr.sin_addr.s_addr ? ast_inet_ntoa(device->addr.sin_addr) : "", ntohs(device->addr.sin_port));
00596       astman_append(s, "Default-addr-IP: %s\r\nDefault-addr-port: %d\r\n", ast_inet_ntoa(device->defaddr.sin_addr), ntohs(device->defaddr.sin_port));
00597       astman_append(s, "Default-Username: %s\r\n", device->defaultuser);
00598       if (!ast_strlen_zero(global.regcontext))
00599          astman_append(s, "RegExtension: %s\r\n", device->extra.regexten);
00600       astman_append(s, "Codecs: ");
00601       ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, device->capability);
00602       astman_append(s, "%s\r\n", codec_buf);
00603       astman_append(s, "CodecOrder: ");
00604       pref = &device->prefs;
00605       for(x = 0; x < 32 ; x++) {
00606          codec = ast_codec_pref_index(pref,x);
00607          if (!codec)
00608             break;
00609          astman_append(s, "%s", ast_getformatname(codec));
00610          if (x < 31 && ast_codec_pref_index(pref,x+1))
00611             astman_append(s, ",");
00612       }
00613 
00614       astman_append(s, "\r\n");
00615       astman_append(s, "Status: ");
00616       device_status(device, status, sizeof(status));
00617       astman_append(s, "%s\r\n", status);
00618       astman_append(s, "SIP-Useragent: %s\r\n", device->useragent);
00619       astman_append(s, "Reg-Contact : %s\r\n", device->fullcontact);
00620       if (device->chanvars) {
00621          for (v = device->chanvars ; v ; v = v->next) {
00622             astman_append(s, "ChanVariable:\n");
00623             astman_append(s, " %s,%s\r\n", v->name, v->value);
00624          }
00625       }
00626 
00627       device_unref(device);
00628 
00629    } else {
00630       ast_cli(fd,"Device %s not found.\n", argv[3]);
00631       ast_cli(fd,"\n");
00632    }
00633 
00634    return RESULT_SUCCESS;
00635 }
00636 
00637 /*! \brief Show one peer in detail */
00638 static int sip_show_device(int fd, int argc, const char *argv[])
00639 {
00640    return _sip_show_device(0, fd, NULL, NULL, argc, argv);
00641 }
00642 
00643 /*! \brief Show SIP peers in the manager API  */
00644 int manager_sip_show_device( struct mansession *s, const struct message *m)
00645 {
00646    const char *id = astman_get_header(m,"ActionID");
00647    const char *a[4];
00648    const char *peer;
00649    int ret;
00650 
00651    peer = astman_get_header(m,"Peer");
00652    if (ast_strlen_zero(peer)) {
00653       astman_send_error(s, m, "Peer: <name> missing.\n");
00654       return 0;
00655    }
00656    a[0] = "sip3";
00657    a[1] = "show";
00658    a[2] = "peer";
00659    a[3] = peer;
00660 
00661    if (!ast_strlen_zero(id))
00662       astman_append(s, "ActionID: %s\r\n",id);
00663    ret = _sip_show_device(1, -1, s, m, 4, a );
00664    astman_append(s, "\r\n\r\n" );
00665    return ret;
00666 }
00667 
00668 
00669 
00670 /*! \brief  Show SIP Registry (registrations with other SIP proxies */
00671 static int sip_show_registry(int fd, int argc, char *argv[])
00672 {
00673 #define FORMAT2 "%-30.30s  %-12.12s  %8.8s %-20.20s %-25.25s\n"
00674 #define FORMAT  "%-30.30s  %-12.12s  %8d %-20.20s %-25.25s\n"
00675    char host[80];
00676    char tmpdat[256];
00677    struct tm tm;
00678 
00679 
00680    if (argc != 3)
00681       return RESULT_SHOWUSAGE;
00682    ast_cli(fd, FORMAT2, "Host", "Username", "Refresh", "State", "Reg.Time");
00683    ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do {
00684       ASTOBJ_RDLOCK(iterator);
00685       snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT);
00686       if (iterator->regtime) {
00687          ast_localtime(&iterator->regtime, &tm, NULL);
00688          strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T", &tm);
00689       } else {
00690          tmpdat[0] = 0;
00691       }
00692       ast_cli(fd, FORMAT, host, iterator->username, iterator->refresh, regstate2str(iterator->regstate), tmpdat);
00693       ASTOBJ_UNLOCK(iterator);
00694    } while(0));
00695    return RESULT_SUCCESS;
00696 #undef FORMAT
00697 #undef FORMAT2
00698 }
00699 
00700 /*! \brief List global settings for the SIP channel */
00701 static int sip_show_settings(int fd, int argc, char *argv[])
00702 {
00703    int realtimepeers;
00704    int realtimeusers;
00705 
00706    realtimepeers = ast_check_realtime("sip3peers");
00707    realtimeusers = ast_check_realtime("sip3users");
00708 
00709    if (argc != 3)
00710       return RESULT_SHOWUSAGE;
00711    ast_cli(fd, "\n\nGlobal Settings:\n");
00712    ast_cli(fd, "----------------\n");
00713    ast_cli(fd, "  SIP Port:               %d\n", ntohs(sipnet.bindaddr.sin_port));
00714    ast_cli(fd, "  Bindaddress:            %s\n", ast_inet_ntoa(sipnet.bindaddr.sin_addr));
00715    ast_cli(fd, "  Videosupport:           %s\n", ast_test_flag(&global.flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "Yes" : "No");
00716    ast_cli(fd, "  AutoCreatePeer:         %s\n", global.autocreatepeer ? "Yes" : "No");
00717    ast_cli(fd, "  Allow unknown access:   %s\n", global.allowguest ? "Yes" : "No");
00718    ast_cli(fd, "  Allow subscriptions:    %s\n", ast_test_flag(&global.flags[1], SIP_PAGE2_ALLOWSUBSCRIBE) ? "Yes" : "No");
00719    ast_cli(fd, "  Allow overlap dialing:  %s\n", ast_test_flag(&global.flags[1], SIP_PAGE2_ALLOWOVERLAP) ? "Yes" : "No");
00720    ast_cli(fd, "  Promsic. redir:         %s\n", ast_test_flag(&global.flags[0], SIP_PROMISCREDIR) ? "Yes" : "No");
00721    ast_cli(fd, "  SIP domain support:     %s\n", domains_configured() ? "No" : "Yes");
00722    ast_cli(fd, "  Call to non-local dom.: %s\n", global.allow_external_domains ? "Yes" : "No");
00723    ast_cli(fd, "  URI user is phone no:   %s\n", ast_test_flag(&global.flags[0], SIP_USEREQPHONE) ? "Yes" : "No");
00724    ast_cli(fd, "  Our auth realm          %s\n", global.realm);
00725    ast_cli(fd, "  Realm. auth:            %s\n", authl ? "Yes": "No");
00726    ast_cli(fd, "  Always auth rejects:    %s\n", global.alwaysauthreject ? "Yes" : "No");
00727    ast_cli(fd, "  User Agent:             %s\n", global.useragent);
00728    ast_cli(fd, "  MWI checking interval:  %d secs\n", global.mwitime);
00729    ast_cli(fd, "  Reg. context:           %s\n", S_OR(global.regcontext, "(not set)"));
00730    ast_cli(fd, "  Caller ID:              %s\n", global.default_callerid);
00731    ast_cli(fd, "  From: Domain:           %s\n", global.default_fromdomain);
00732    ast_cli(fd, "  Record SIP history:     %s\n", global.recordhistory ? "On" : "Off");
00733    ast_cli(fd, "  Call Events:            %s\n", global.callevents ? "On" : "Off");
00734    ast_cli(fd, "  IP ToS SIP:             %s\n", ast_tos2str(global.tos_sip));
00735    ast_cli(fd, "  IP ToS RTP audio:       %s\n", ast_tos2str(global.tos_audio));
00736    ast_cli(fd, "  IP ToS RTP video:       %s\n", ast_tos2str(global.tos_video));
00737    ast_cli(fd, "  IP ToS SIP presence:    %s\n", ast_tos2str(global.tos_presense));
00738    ast_cli(fd, "  T38 fax pt UDPTL:       %s\n", ast_test_flag(&global.flags[1], SIP_PAGE2_T38SUPPORT_UDPTL) ? "Yes" : "No");
00739    ast_cli(fd, "  T38 fax pt RTP:         %s\n", ast_test_flag(&global.flags[1], SIP_PAGE2_T38SUPPORT_RTP) ? "Yes" : "No");
00740    ast_cli(fd, "  T38 fax pt TCP:         %s\n", ast_test_flag(&global.flags[1], SIP_PAGE2_T38SUPPORT_TCP) ? "Yes" : "No");
00741    ast_cli(fd, "  RFC2833 Compensation:   %s\n", ast_test_flag(&global.flags[1], SIP_PAGE2_RFC2833_COMPENSATE) ? "Yes" : "No");
00742    ast_cli(fd, "  Jitterbuffer enabled:   %s\n", ast_test_flag(&global.jbconf, AST_JB_ENABLED) ? "Yes" : "No");
00743    ast_cli(fd, "  Jitterbuffer forced:    %s\n", ast_test_flag(&global.jbconf, AST_JB_FORCED) ? "Yes" : "No");
00744    ast_cli(fd, "  Jitterbuffer max size:  %ld\n", global.jbconf.max_size);
00745    ast_cli(fd, "  Jitterbuffer resync:    %ld\n", global.jbconf.resync_threshold);
00746    ast_cli(fd, "  Jitterbuffer impl:      %s\n", global.jbconf.impl);
00747    ast_cli(fd, "  Jitterbuffer log:       %s\n", ast_test_flag(&global.jbconf, AST_JB_LOG) ? "Yes" : "No");
00748    ast_cli(fd, "  SIP debug level:        %s\n", global.debuglevel == SIPDEBUG_ALL ? "Everything" : (global.debuglevel == SIPDEBUG_CALLS ? "Calls" : "No OPTION messages"));
00749    if (!realtimepeers && !realtimeusers)
00750       ast_cli(fd, "  SIP realtime:           Disabled\n" );
00751    else
00752       ast_cli(fd, "  SIP realtime:           Enabled\n" );
00753 
00754    ast_cli(fd, "\nGlobal Signalling Settings:\n");
00755    ast_cli(fd, "---------------------------\n");
00756    ast_cli(fd, "  Codecs:                 ");
00757    print_codec_to_cli(fd, &global.default_prefs);
00758    ast_cli(fd, "\n");
00759    ast_cli(fd, "  Relax DTMF:             %s\n", global.relaxdtmf ? "Yes" : "No");
00760    ast_cli(fd, "  Compact SIP headers:    %s\n", global.compactheaders ? "Yes" : "No");
00761    ast_cli(fd, "  RTP Keepalive:          %d %s\n", global.rtptimer.rtpkeepalive, global.rtptimer.rtpkeepalive ? "" : "(Disabled)" );
00762    ast_cli(fd, "  RTP Timeout:            %d %s\n", global.rtptimer.rtptimeout, global.rtptimer.rtptimeout ? "" : "(Disabled)" );
00763    ast_cli(fd, "  RTP Hold Timeout:       %d %s\n", global.rtptimer.rtpholdtimeout, global.rtptimer.rtpholdtimeout ? "" : "(Disabled)");
00764    ast_cli(fd, "  MWI NOTIFY mime type:   %s\n", global.default_notifymime);
00765    ast_cli(fd, "  DNS SRV lookup:         %s\n", global.srvlookup ? "Yes" : "No");
00766    ast_cli(fd, "  Reg. min duration       %d secs\n", expiry.min_expiry);
00767    ast_cli(fd, "  Reg. max duration:      %d secs\n", expiry.max_expiry);
00768    ast_cli(fd, "  Reg. default duration:  %d secs\n", expiry.default_expiry);
00769    ast_cli(fd, "  Outbound reg. timeout:  %d secs\n", global.reg_timeout);
00770    ast_cli(fd, "  Outbound reg. attempts: %d\n", global.regattempts_max);
00771    ast_cli(fd, "  Notify ringing state:   %s\n", global.notifyringing ? "Yes" : "No");
00772    ast_cli(fd, "  SIP Transfer mode:      %s\n", transfermode2str(global.allowtransfer));
00773    ast_cli(fd, "  Max Call Bitrate:       %d kbps\r\n", global.default_maxcallbitrate);
00774    ast_cli(fd, "\nTimer Settings:\n");
00775    ast_cli(fd, "-----------------\n");
00776    ast_cli(fd, "  SIP Timer T1 minimum: %d\n", global.t1min);
00777    ast_cli(fd, "  SIP Timer T1 default: %d\n", global.t1default);
00778    ast_cli(fd, "  SIP Timer T2:         %d\n", global.t2default);
00779    ast_cli(fd, "  SIP Timer T4:         %d\n", global.t4default);
00780    ast_cli(fd, "  SIP Timer B:          %d\n", global.siptimer_b);
00781    ast_cli(fd, "  SIP Timer F:          %d\n", global.siptimer_f);
00782    ast_cli(fd, "\nDefault Settings:\n");
00783    ast_cli(fd, "-----------------\n");
00784    ast_cli(fd, "  Context:                %s\n", global.default_context);
00785    ast_cli(fd, "  Nat:                    %s\n", nat2str(ast_test_flag(&global.flags[0], SIP_NAT)));
00786    ast_cli(fd, "  DTMF:                   %s\n", dtmfmode2str(ast_test_flag(&global.flags[0], SIP_DTMF)));
00787    ast_cli(fd, "  Qualify:                %d\n", global.default_qualify);
00788    ast_cli(fd, "  Qualify timer OK:       %d sec\n", global.default_qualifycheck_ok);
00789    ast_cli(fd, "  Qualify timer not OK:   %d sec\n", global.default_qualifycheck_notok);
00790    ast_cli(fd, "  Use ClientCode:         %s\n", ast_test_flag(&global.flags[0], SIP_USECLIENTCODE) ? "Yes" : "No");
00791    ast_cli(fd, "  Progress inband:        %s\n", (ast_test_flag(&global.flags[0], SIP_PROG_INBAND) == SIP_PROG_INBAND_NEVER) ? "Never" : (ast_test_flag(&global.flags[0], SIP_PROG_INBAND) == SIP_PROG_INBAND_NO) ? "No" : "Yes" );
00792    ast_cli(fd, "  Language:               %s\n", S_OR(global.default_language, "(Defaults to English)"));
00793    ast_cli(fd, "  MOH Interpret:          %s\n", global.default_mohinterpret);
00794    ast_cli(fd, "  MOH Suggest:            %s\n", global.default_mohsuggest);
00795    ast_cli(fd, "  Voice Mail Extension:   %s\n", global.default_vmexten);
00796 
00797    
00798    if (realtimepeers || realtimeusers) {
00799       ast_cli(fd, "\nRealtime SIP Settings:\n");
00800       ast_cli(fd, "----------------------\n");
00801       ast_cli(fd, "  Realtime Peers:         %s\n", realtimepeers ? "Yes" : "No");
00802       ast_cli(fd, "  Realtime Users:         %s\n", realtimeusers ? "Yes" : "No");
00803       ast_cli(fd, "  Cache Friends:          %s\n", ast_test_flag(&global.flags[1], SIP_PAGE2_RTCACHEFRIENDS) ? "Yes" : "No");
00804       ast_cli(fd, "  Update:                 %s\n", ast_test_flag(&global.flags[1], SIP_PAGE2_RTUPDATE) ? "Yes" : "No");
00805       ast_cli(fd, "  Ignore Reg. Expire:     %s\n", ast_test_flag(&global.flags[1], SIP_PAGE2_IGNOREREGEXPIRE) ? "Yes" : "No");
00806       ast_cli(fd, "  Save sys. name:         %s\n", ast_test_flag(&global.flags[1], SIP_PAGE2_RTSAVE_SYSNAME) ? "Yes" : "No");
00807       ast_cli(fd, "  Auto Clear:             %d\n", global.rtautoclear);
00808    }
00809    ast_cli(fd, "\n----\n");
00810    return RESULT_SUCCESS;
00811 }
00812 
00813 /*! \brief Show details of one active dialog */
00814 static int sip_show_channel(int fd, int argc, char *argv[])
00815 {
00816    struct sip_dialog *cur;
00817    size_t len;
00818    int found = 0;
00819 
00820    if (argc != 4)
00821       return RESULT_SHOWUSAGE;
00822    len = strlen(argv[3]);
00823    dialoglist_lock();
00824    for (cur = dialoglist; cur; cur = cur->next) {
00825       if (!strncasecmp(cur->callid, argv[3], len)) {
00826          char formatbuf[BUFSIZ/2];
00827          ast_cli(fd,"\n");
00828          if (cur->subscribed != NONE)
00829             ast_cli(fd, "  * Subscription (type: %s)\n", subscription_type2str(cur->subscribed));
00830          else
00831             ast_cli(fd, "  * SIP Call\n");
00832          ast_cli(fd, "  State:                  %s\n", dialogstate2str(cur->state));
00833          ast_cli(fd, "  Direction:              %s\n", ast_test_flag(&cur->flags[0], SIP_OUTGOING)?"Outgoing":"Incoming");
00834          ast_cli(fd, "  Call-ID:                %s\n", cur->callid);
00835          ast_cli(fd, "  Owner channel ID:       %s\n", cur->owner ? cur->owner->name : "<none>");
00836          ast_cli(fd, "  Our Codec Capability:   %d\n", cur->capability);
00837          ast_cli(fd, "  Non-Codec Capability (DTMF):   %d\n", cur->noncodeccapability);
00838          ast_cli(fd, "  Their Codec Capability:   %d\n", cur->peercapability);
00839          ast_cli(fd, "  Joint Codec Capability:   %d\n", cur->jointcapability);
00840          ast_cli(fd, "  Format:                 %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner ? cur->owner->nativeformats : 0) );
00841          ast_cli(fd, "  T.38 support            %s\n", cur->udptl ? "Yes" : "No");
00842          ast_cli(fd, "  Video support           %s\n", cur->vrtp ? "Yes" : "No");
00843          ast_cli(fd, "  MaxCallBR:              %d kbps\n", cur->maxcallbitrate);
00844          ast_cli(fd, "  Theoretical Address:    %s:%d\n", ast_inet_ntoa(cur->sa.sin_addr), ntohs(cur->sa.sin_port));
00845          ast_cli(fd, "  Received Address:       %s:%d\n", ast_inet_ntoa(cur->recv.sin_addr), ntohs(cur->recv.sin_port));
00846          ast_cli(fd, "  SIP Transfer mode:      %s\n", transfermode2str(cur->allowtransfer));
00847          ast_cli(fd, "  NAT Support:            %s\n", nat2str(ast_test_flag(&cur->flags[0], SIP_NAT)));
00848          ast_cli(fd, "  Audio IP:               %s %s\n", ast_inet_ntoa(cur->redirip.sin_addr.s_addr ? cur->redirip.sin_addr : cur->ourip), cur->redirip.sin_addr.s_addr ? "(Outside bridge)" : "(local)" );
00849          ast_cli(fd, "  Our Tag:                %s\n", cur->tag);
00850          ast_cli(fd, "  Their Tag:              %s\n", cur->theirtag);
00851          ast_cli(fd, "  SIP User agent:         %s\n", cur->useragent);
00852          if (!ast_strlen_zero(cur->username))
00853             ast_cli(fd, "  Username:               %s\n", cur->username);
00854          if (!ast_strlen_zero(cur->peername))
00855             ast_cli(fd, "  Peername:               %s\n", cur->peername);
00856          if (!ast_strlen_zero(cur->uri))
00857             ast_cli(fd, "  Original uri:           %s\n", cur->uri);
00858          if (!ast_strlen_zero(cur->cid_num))
00859             ast_cli(fd, "  Caller-ID:              %s\n", cur->cid_num);
00860          ast_cli(fd, "  Need Destroy:           %d\n", ast_test_flag(&cur->flags[0], SIP_NEEDDESTROY));
00861          ast_cli(fd, "  Last Message:           %s\n", cur->lastmsg);
00862          ast_cli(fd, "  Promiscuous Redir:      %s\n", ast_test_flag(&cur->flags[0], SIP_PROMISCREDIR) ? "Yes" : "No");
00863          ast_cli(fd, "  Route:                  %s\n", cur->route ? cur->route->hop : "N/A");
00864          ast_cli(fd, "  DTMF Mode:              %s\n", dtmfmode2str(ast_test_flag(&cur->flags[0], SIP_DTMF)));
00865          ast_cli(fd, "  SIP Options:            ");
00866          if (cur->sipoptions) {
00867             sip_options_print(cur->sipoptions, fd);
00868          } else
00869             ast_cli(fd, "(none)\n");
00870          ast_cli(fd, "\n\n");
00871          found++;
00872       }
00873    }
00874    dialoglist_unlock();
00875    if (!found) 
00876       ast_cli(fd, "No such SIP Call ID starting with '%s'\n", argv[3]);
00877    return RESULT_SUCCESS;
00878 }
00879 
00880 /*! \brief Show history details of one dialog */
00881 static int sip_show_history(int fd, int argc, char *argv[])
00882 {
00883    struct sip_dialog *cur;
00884    size_t len;
00885    int found = 0;
00886 
00887    if (argc != 4)
00888       return RESULT_SHOWUSAGE;
00889    if (!global.recordhistory)
00890       ast_cli(fd, "\n***Note: History recording is currently DISABLED.  Use 'sip history' to ENABLE.\n");
00891    len = strlen(argv[3]);
00892    dialoglist_lock();
00893    for (cur = dialoglist; cur; cur = cur->next) {
00894       if (!strncasecmp(cur->callid, argv[3], len)) {
00895          struct sip_history *hist;
00896          int x = 0;
00897 
00898          ast_cli(fd,"\n");
00899          if (cur->subscribed != NONE)
00900             ast_cli(fd, "  * Subscription\n");
00901          else
00902             ast_cli(fd, "  * SIP Call\n");
00903          if (cur->history) {
00904             AST_LIST_TRAVERSE(cur->history, hist, list)
00905                ast_cli(fd, "%d. %s\n", ++x, hist->event);
00906          }
00907          if (x == 0)
00908             ast_cli(fd, "Call '%s' has no history\n", cur->callid);
00909          found++;
00910       }
00911    }
00912    dialoglist_unlock();
00913    if (!found) 
00914       ast_cli(fd, "No such SIP Call ID starting with '%s'\n", argv[3]);
00915    return RESULT_SUCCESS;
00916 }
00917 
00918 /*! \brief Do completion on peer name */
00919 GNURK char *complete_sip_device(const char *word, int state, int flags2)
00920 {
00921    char *result = NULL;
00922    int wordlen = strlen(word);
00923    int which = 0;
00924 
00925    ASTOBJ_CONTAINER_TRAVERSE(&devicelist, !result, do {
00926       /* locking of the object is not required because only the name and flags are being compared */
00927       if (!strncasecmp(word, iterator->name, wordlen) &&
00928             (!flags2 || ast_test_flag(&iterator->flags[1], flags2)) &&
00929             ++which > state)
00930          result = ast_strdup(iterator->name);
00931    } while(0) );
00932    return result;
00933 }
00934 
00935 /*! \brief Support routine for 'sip show peer' CLI */
00936 GNURK char *complete_sip_show_device(const char *line, const char *word, int pos, int state)
00937 {
00938    if (pos == 3)
00939       return complete_sip_device(word, state, 0);
00940 
00941    return NULL;
00942 }
00943 
00944 /*! \brief Support routine for 'sip show channel' CLI */
00945 static char *complete_sipch(const char *line, const char *word, int pos, int state)
00946 {
00947    int which=0;
00948    struct sip_dialog *cur;
00949    char *c = NULL;
00950    int wordlen = strlen(word);
00951 
00952    dialoglist_lock();
00953    for (cur = dialoglist; cur; cur = cur->next) {
00954       if (!strncasecmp(word, cur->callid, wordlen) && ++which > state) {
00955          c = ast_strdup(cur->callid);
00956          break;
00957       }
00958    }
00959    dialoglist_unlock();
00960    return c;
00961 }
00962 
00963 
00964 /*! \brief Support routine for 'sip debug peer' CLI */
00965 static char *complete_sip_debug_device(const char *line, const char *word, int pos, int state)
00966 {
00967    if (pos == 3)
00968       return complete_sip_device(word, state, 0);
00969 
00970    return NULL;
00971 }
00972 
00973 
00974 /*! \brief SIP show channels CLI (main function) */
00975 static int __sip_show_channels(int fd, int argc, char *argv[], int subscriptions)
00976 {
00977 #define FORMAT3 "%-15.15s  %-10.10s  %-11.11s  %-15.15s  %-13.13s  %-15.15s %-10.10s\n"
00978 #define FORMAT2 "%-15.15s  %-10.10s  %-11.11s  %-11.11s  %-4.4s  %-7.7s  %-15.15s\n"
00979 #define FORMAT  "%-15.15s  %-10.10s  %-11.11s  %5.5d/%5.5d  %-4.4s  %-3.3s %-3.3s  %-15.15s %-10.10s\n"
00980    struct sip_dialog *cur;
00981    int numchans = 0;
00982    const char *referstatus = NULL;
00983 
00984    if (argc != 3)
00985       return RESULT_SHOWUSAGE;
00986    dialoglist_lock();
00987    cur = dialoglist;
00988    if (!subscriptions)
00989       ast_cli(fd, FORMAT2, "Peer", "User/ANR", "Call ID", "Seq (Tx/Rx)", "Format", "Hold", "Last Message");
00990    else 
00991       ast_cli(fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type", "Mailbox");
00992    for (; cur; cur = cur->next) {
00993       dialoglist_unlock();
00994       referstatus = "";
00995       if (cur->refer) { /* SIP transfer in progress */
00996          referstatus = referstatus2str(cur->refer->status);
00997       }
00998       if (cur->subscribed == NONE && !subscriptions) {
00999          ast_cli(fd, FORMAT, ast_inet_ntoa(cur->sa.sin_addr), 
01000             S_OR(cur->username, S_OR(cur->cid_num, "(None)")),
01001             cur->callid, 
01002             cur->ocseq, cur->icseq, 
01003             ast_getformatname(cur->owner ? cur->owner->nativeformats : 0), 
01004             ast_test_flag(&cur->flags[1], SIP_PAGE2_CALL_ONHOLD) ? "Yes" : "No",
01005             ast_test_flag(&cur->flags[0], SIP_NEEDDESTROY) ? "(d)" : "",
01006             cur->lastmsg ,
01007             referstatus
01008          );
01009          numchans++;
01010       }
01011       if (cur->subscribed != NONE && subscriptions) {
01012          ast_cli(fd, FORMAT3, ast_inet_ntoa(cur->sa.sin_addr),
01013             S_OR(cur->username, S_OR(cur->cid_num, "(None)")), 
01014                cur->callid,
01015             /* the 'complete' exten/context is hidden in the refer_to field for subscriptions */
01016             cur->subscribed == MWI_NOTIFICATION ? "--" : cur->subscribeuri,
01017             cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate), 
01018             subscription_type2str(cur->subscribed),
01019             cur->subscribed == MWI_NOTIFICATION ? (cur->relatedpeer ? cur->relatedpeer->mailbox.mailbox : "<none>") : "<none>"
01020 );
01021          numchans++;
01022       }
01023       dialoglist_lock();
01024    }
01025    dialoglist_unlock();
01026    if (!subscriptions)
01027       ast_cli(fd, "%d active SIP channel%s\n", numchans, (numchans != 1) ? "s" : "");
01028    else
01029       ast_cli(fd, "%d active SIP subscription%s\n", numchans, (numchans != 1) ? "s" : "");
01030    return RESULT_SUCCESS;
01031 #undef FORMAT
01032 #undef FORMAT2
01033 #undef FORMAT3
01034 }
01035 
01036 /*! \brief Show active SIP channels */
01037 static int sip_show_channels(int fd, int argc, char *argv[])  
01038 {
01039         return __sip_show_channels(fd, argc, argv, 0);
01040 }
01041  
01042 /*! \brief Show active SIP subscriptions */
01043 static int sip_show_subscriptions(int fd, int argc, char *argv[])
01044 {
01045         return __sip_show_channels(fd, argc, argv, 1);
01046 }
01047 
01048 
01049 /*! \brief Start reload process from CLI */
01050 static  int cli_sip_reload(int fd, int argc, char *argv[])
01051 {
01052    return sip_reload(fd);
01053    
01054 }
01055 
01056 /*! \brief List configuration options */
01057 static  int cli_sip_listconfigs(int fd, int argc, char *argv[])
01058 {
01059    return sip_listconfigs(fd);
01060 }
01061 
01062 
01063 /*! \brief Enable SIP Debugging in CLI */
01064 static int sip_do_debug_ip(int fd, int argc, char *argv[])
01065 {
01066    struct hostent *hp;
01067    struct ast_hostent ahp;
01068    int port = 0;
01069    char *p, *arg;
01070 
01071    if (argc != 4)
01072       return RESULT_SHOWUSAGE;
01073    p = arg = argv[3];
01074    strsep(&p, ":");
01075    if (p)
01076       port = atoi(p);
01077    hp = ast_gethostbyname(arg, &ahp);
01078    if (hp == NULL)
01079       return RESULT_SHOWUSAGE;
01080 
01081    sipnet.debugaddr.sin_family = AF_INET;
01082    memcpy(&sipnet.debugaddr.sin_addr, hp->h_addr, sizeof(sipnet.debugaddr.sin_addr));
01083    sipnet.debugaddr.sin_port = htons(port);
01084    if (port == 0)
01085       ast_cli(fd, "SIP Debugging Enabled for IP: %s\n", ast_inet_ntoa(sipnet.debugaddr.sin_addr));
01086    else
01087       ast_cli(fd, "SIP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(sipnet.debugaddr.sin_addr), port);
01088 
01089    ast_set_flag(&global.flags[1], SIP_PAGE2_DEBUG_CONSOLE);
01090 
01091    return RESULT_SUCCESS;
01092 }
01093 
01094 
01095 /*! \brief  sip_do_debug_device: Turn on SIP debugging with peer mask */
01096 static int sip_do_debug_device(int fd, int argc, char *argv[])
01097 {
01098    struct sip_device *peer;
01099    if (argc != 4)
01100       return RESULT_SHOWUSAGE;
01101    peer = find_device(argv[3], NULL, 1);
01102    if (peer) {
01103       if (peer->addr.sin_addr.s_addr) {
01104          sipnet.debugaddr.sin_family = AF_INET;
01105          sipnet.debugaddr.sin_addr = peer->addr.sin_addr;
01106          sipnet.debugaddr.sin_port = peer->addr.sin_port;
01107          ast_cli(fd, "SIP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(sipnet.debugaddr.sin_addr), ntohs(sipnet.debugaddr.sin_port));
01108          ast_set_flag(&global.flags[1], SIP_PAGE2_DEBUG_CONSOLE);
01109       } else
01110          ast_cli(fd, "Unable to get IP address of peer '%s'\n", argv[3]);
01111       device_unref(peer);
01112    } else
01113       ast_cli(fd, "No such peer '%s'\n", argv[3]);
01114    return RESULT_SUCCESS;
01115 }
01116 
01117 /*! \brief Turn on SIP debugging (CLI command) */
01118 static int sip_do_debug(int fd, int argc, char *argv[])
01119 {
01120    int oldsipdebug = sipdebug_console;
01121    if (argc != 3) {
01122       if (argc != 4) 
01123          return RESULT_SHOWUSAGE;
01124       else if (strcmp(argv[2], "ip") == 0)
01125          return sip_do_debug_ip(fd, argc, argv);
01126       else if (strcmp(argv[2], "peer") == 0)
01127          return sip_do_debug_device(fd, argc, argv);
01128       else
01129          return RESULT_SHOWUSAGE;
01130    }
01131    ast_set_flag(&global.flags[1], SIP_PAGE2_DEBUG_CONSOLE);
01132    memset(&sipnet.debugaddr, 0, sizeof(sipnet.debugaddr));
01133    ast_cli(fd, "SIP Debugging %senabled\n", oldsipdebug ? "re-" : "");
01134    return RESULT_SUCCESS;
01135 }
01136 
01137 /*! \brief Disable SIP Debugging in CLI */
01138 static int sip_no_debug(int fd, int argc, char *argv[])
01139 {
01140    if (argc != 3)
01141       return RESULT_SHOWUSAGE;
01142    ast_clear_flag(&global.flags[1], SIP_PAGE2_DEBUG_CONSOLE);
01143    ast_cli(fd, "SIP Debugging Disabled\n");
01144    return RESULT_SUCCESS;
01145 }
01146 
01147 
01148 /*! \brief Enable SIP History logging (CLI) */
01149 static int sip_do_history(int fd, int argc, char *argv[])
01150 {
01151    if (argc != 3) {
01152       return RESULT_SHOWUSAGE;
01153    }
01154    global.recordhistory = TRUE;
01155    ast_cli(fd, "SIP History Recording Enabled (use 'sip show history')\n");
01156    return RESULT_SUCCESS;
01157 }
01158 
01159 /*! \brief Disable SIP History logging (CLI) */
01160 static int sip_no_history(int fd, int argc, char *argv[])
01161 {
01162    if (argc != 3) {
01163       return RESULT_SHOWUSAGE;
01164    }
01165    global.recordhistory = FALSE;
01166    ast_cli(fd, "SIP History Recording Disabled\n");
01167    return RESULT_SUCCESS;
01168 }
01169 
01170 
01171 /*! \brief Support routine for 'sip notify' CLI */
01172 static char *complete_sipnotify(const char *line, const char *word, int pos, int state)
01173 {
01174    char *c = NULL;
01175 
01176    if (pos == 2) {
01177       int which = 0;
01178       char *cat = NULL;
01179       int wordlen = strlen(word);
01180 
01181       /* do completion for notify type */
01182 
01183       if (!notify_types)
01184          return NULL;
01185       
01186       while ( (cat = ast_category_browse(notify_types, cat)) ) {
01187          if (!strncasecmp(word, cat, wordlen) && ++which > state) {
01188             c = ast_strdup(cat);
01189             break;
01190          }
01191       }
01192       return c;
01193    }
01194 
01195    if (pos > 2)
01196       return complete_sip_device(word, state, 0);
01197 
01198    return NULL;
01199 }
01200 
01201 /*! \brief Support routine for 'sip prune realtime peer' CLI */
01202 static char *complete_sip_prune_realtime_peer(const char *line, const char *word, int pos, int state)
01203 {
01204    if (pos == 4)
01205       return complete_sip_device(word, state, SIP_PAGE2_RTCACHEFRIENDS);
01206    return NULL;
01207 }
01208 
01209 static char show_domains_usage[] = 
01210 "Usage: sip list domains\n"
01211 "       Lists all configured SIP local domains.\n"
01212 "       Asterisk only responds to SIP messages to local domains.\n";
01213 
01214 static char notify_usage[] =
01215 "Usage: sip notify <type> <peer> [<peer>...]\n"
01216 "       Send a NOTIFY message to a SIP peer or peers\n"
01217 "       Message types are defined in sip_notify.conf\n";
01218 
01219 static char show_inuse_usage[] = 
01220 "Usage: sip list inuse [all]\n"
01221 "       List all SIP users and peers usage counters and limits.\n"
01222 "       Add option \"all\" to show all devices, not only those with a limit.\n";
01223 
01224 static char show_channels_usage[] = 
01225 "Usage: sip list channels\n"
01226 "       Lists all currently active SIP channels.\n";
01227 
01228 static char show_channel_usage[] = 
01229 "Usage: sip show channel <channel>\n"
01230 "       Provides detailed status on a given SIP channel.\n";
01231 
01232 static char show_history_usage[] = 
01233 "Usage: sip show history <channel>\n"
01234 "       Provides detailed dialog history on a given SIP channel.\n";
01235 
01236 static char show_devices_usage[] = 
01237 "Usage: sip list devices [like <pattern>]\n"
01238 "       Lists all known SIP devices.\n"
01239 "       Optional regular expression pattern is used to filter the devices list.\n";
01240 
01241 static char show_device_usage[] =
01242 "Usage: sip show device <name> [load]\n"
01243 "       Shows all details on one SIP device and the current status.\n"
01244 "       Option \"load\" forces lookup of peer in realtime storage.\n";
01245 
01246 static char prune_realtime_usage[] =
01247 "Usage: sip prune realtime peer [<name>|all|like <pattern>]\n"
01248 "       Prunes object(s) from the cache.\n"
01249 "       Optional regular expression pattern is used to filter the objects.\n";
01250 
01251 static char show_reg_usage[] =
01252 "Usage: sip list registry\n"
01253 "       Lists all service registration requests and status.\n";
01254 
01255 static char debug_usage[] = 
01256 "Usage: sip debug on/off\n"
01257 "       Enables dumping of SIP packets for debugging purposes\n\n"
01258 "       sip debug ip <host[:PORT]>\n"
01259 "       Enables dumping of SIP packets to and from host.\n\n"
01260 "       sip debug peer <peername>\n"
01261 "       Enables dumping of SIP packets to and from host.\n"
01262 "       Require peer to be registered.\n";
01263 
01264 static char no_debug_usage[] = 
01265 "Usage: sip debug off\n"
01266 "       Disables dumping of SIP packets for debugging purposes\n";
01267 
01268 static char no_history_usage[] = 
01269 "Usage: sip history off\n"
01270 "       Disables recording of SIP dialog history for debugging purposes\n";
01271 
01272 static char history_usage[] = 
01273 "Usage: sip history on\n"
01274 "       Enables recording of SIP dialog history for debugging purposes.\n"
01275 "Use 'sip show history' to view the history of a call number.\n";
01276 
01277 static char sip_reload_usage[] =
01278 "Usage: sip reload\n"
01279 "       Reloads SIP configuration from sip.conf\n";
01280 
01281 static char show_subscriptions_usage[] =
01282 "Usage: sip list subscriptions\n" 
01283 "       Lists active SIP subscriptions for extension states\n";
01284 
01285 static char show_objects_usage[] =
01286 "Usage: sip list objects\n" 
01287 "       Lists status of known SIP objects\n";
01288 
01289 static char show_settings_usage[] = 
01290 "Usage: sip list settings\n"
01291 "       Provides detailed list of the configuration of the SIP channel.\n";
01292 
01293 static char sip_listconfig_usage[] = 
01294 "Usage: sip list configs\n"
01295 "       Provides detailed list of the configuration options of the SIP channel.\n";
01296 
01297 
01298 static struct ast_cli_entry cli_sip[] = {
01299    { { "sip", "show", "channels", NULL },
01300    sip_show_channels, "List active SIP channels",
01301    show_channels_usage },
01302 
01303    { { "sip", "show", "domains", NULL },
01304    sip_show_domains, "List our local SIP domains.",
01305    show_domains_usage },
01306 
01307    { { "sip", "show", "inuse", NULL },
01308    sip_show_inuse, "List all call limits and their current usage level",
01309    show_inuse_usage },
01310 
01311    { { "sip", "show", "objects", NULL },
01312    sip_show_objects, "List all SIP object allocations",
01313    show_objects_usage },
01314 
01315    { { "sip", "show", "devices", NULL },
01316    sip_show_devices, "List defined SIP devices (phones, trunks, services)",
01317    show_devices_usage },
01318 
01319    { { "sip", "list", "registry", NULL },
01320    sip_show_registry, "List SIP registration status for services",
01321    show_reg_usage },
01322 
01323    { { "sip", "show", "settings", NULL },
01324    sip_show_settings, "Show SIP global settings",
01325    show_settings_usage },
01326 
01327    { { "sip", "show", "subscriptions", NULL },
01328    sip_show_subscriptions, "List active SIP subscriptions",
01329    show_subscriptions_usage },
01330 
01331    { { "sip", "notify", NULL },
01332    sip_notify, "Send a notify packet to a SIP device",
01333    notify_usage, complete_sipnotify },
01334 
01335    { { "sip", "show", "channel", NULL },
01336    sip_show_channel, "Show detailed SIP channel info",
01337    show_channel_usage, complete_sipch  },
01338 
01339    { { "sip", "show", "history", NULL },
01340    sip_show_history, "Show SIP dialog history",
01341    show_history_usage, complete_sipch  },
01342 
01343    { { "sip", "show", "device", NULL },
01344    sip_show_device, "Show details on specific SIP device (phone, service, trunk)",
01345    show_device_usage, complete_sip_show_device },
01346 
01347    { { "sip", "prune", "realtime", NULL },
01348    sip_prune_realtime, "Prune cached Realtime object(s)",
01349    prune_realtime_usage },
01350 
01351    { { "sip", "prune", "realtime", "peer", NULL },
01352    sip_prune_realtime, "Prune cached Realtime peer(s)",
01353    prune_realtime_usage, complete_sip_prune_realtime_peer },
01354 
01355    { { "sip", "debug", "on", NULL },
01356    sip_do_debug, "Enable SIP debugging",
01357    debug_usage },
01358 
01359    { { "sip", "debug", "ip", NULL },
01360    sip_do_debug, "Enable SIP debugging on IP",
01361    debug_usage },
01362 
01363    { { "sip", "debug", "device", NULL },
01364    sip_do_debug, "Enable SIP debugging on device-name",
01365    debug_usage, complete_sip_debug_device },
01366 
01367    { { "sip", "debug", "off", NULL },
01368    sip_no_debug, "Disable SIP debugging",
01369    no_debug_usage },
01370 
01371    { { "sip", "history", "on", NULL },
01372    sip_do_history, "Enable SIP history",
01373    history_usage },
01374 
01375    { { "sip", "history", "off", NULL },
01376    sip_no_history, "Disable SIP history",
01377    no_history_usage },
01378 
01379    { { "sip", "reload", NULL },
01380    cli_sip_reload, "Reload SIP configuration",
01381    sip_reload_usage },
01382 
01383    { { "sip", "list", "configs", NULL },
01384    cli_sip_listconfigs, "List SIP coniguration options",
01385    sip_listconfig_usage },
01386 };
01387 
01388 /*! \brief Register cli and manager commands */
01389 void sip_cli_and_manager_commands_register()
01390 {
01391    /* Register CLI commands */
01392    ast_cli_register_multiple(cli_sip, sizeof(cli_sip)/ sizeof(struct ast_cli_entry));
01393    /* Register manager commands */
01394    ast_manager_register2("SIPdevices", EVENT_FLAG_SYSTEM, manager_sip_show_devices,
01395          "List SIP devices (text format)", mandescr_show_devices);
01396    ast_manager_register2("SIPshowdevice", EVENT_FLAG_SYSTEM, manager_sip_show_device,
01397          "Show SIP device (text format)", mandescr_show_device);
01398 }
01399 
01400 /*! \brief Unregister cli and manager commands */
01401 void sip_cli_and_manager_commands_unregister()
01402 {
01403    ast_cli_unregister_multiple(cli_sip, sizeof(cli_sip) / sizeof(struct ast_cli_entry));
01404    ast_manager_unregister("SIPdevices");
01405    ast_manager_unregister("SIPshowdevice");
01406 }
01407 

Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen