aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--channels/chan_sip.c135
1 files changed, 73 insertions, 62 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index f4ec29c2c..ab1967177 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -210,8 +210,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define SIPBUFSIZE 512
/* Arguments for find_peer */
-#define FINDALLDEVICES FALSE
-#define FINDONLYUSERS TRUE
+#define FINDUSERS (1 << 0)
+#define FINDPEERS (1 << 1)
+#define FINDALLDEVICES (FINDUSERS | FINDPEERS)
#define XMIT_ERROR -2
@@ -1548,7 +1549,6 @@ struct sip_peer {
char rt_fromcontact; /*!< P: copy fromcontact from realtime */
char host_dynamic; /*!< P: Dynamic Peers register with Asterisk */
char selfdestruct; /*!< P: Automatic peers need to destruct themselves */
- char onlymatchonip; /*!< P: Only match on IP for incoming calls (old type=peer) */
char the_mark; /*!< moved out of ASTOBJ into struct proper; That which bears the_mark should be deleted! */
int expire; /*!< When to expire this peer registration */
@@ -2096,14 +2096,14 @@ static void sip_dump_history(struct sip_pvt *dialog);
/*--- Device object handling */
static struct sip_peer *temp_peer(const char *name);
-static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int ispeer);
+static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime);
static int update_call_counter(struct sip_pvt *fup, int event);
static void sip_destroy_peer(struct sip_peer *peer);
static void sip_destroy_peer_fn(void *peer);
static void set_peer_defaults(struct sip_peer *peer);
static struct sip_peer *temp_peer(const char *name);
static void register_peer_exten(struct sip_peer *peer, int onoff);
-static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int forcenamematch, int devstate_only);
+static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int which_objects, int devstate_only);
static int sip_poke_peer_s(const void *data);
static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_request *req);
static void reg_source_db(struct sip_peer *peer);
@@ -4080,7 +4080,7 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
/* Peer found in realtime, now build it in memory */
- peer = build_peer(newpeername, var, varregs, TRUE, FALSE);
+ peer = build_peer(newpeername, var, varregs, TRUE);
if (!peer) {
if(peerlist)
ast_config_destroy(peerlist);
@@ -4125,7 +4125,7 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
*/
struct peer_finding_info {
struct sip_peer tmp_peer;
- int forcenamematch;
+ int which_objects;
};
/* Function to assist finding peers by name only */
@@ -4139,28 +4139,45 @@ static int find_by_name(void *obj, void *arg, int flags)
return 0;
}
- /* If we're only looking for name matches, we should avoid type=peer devices,
- since these should not match on any name-based search */
- if (pfi->forcenamematch && search->onlymatchonip) {
- return 0;
+ switch (pfi->which_objects) {
+ case FINDUSERS:
+ if (!(search->type & SIP_TYPE_USER)) {
+ return 0;
+ }
+ break;
+ case FINDPEERS:
+ if (!(search->type & SIP_TYPE_PEER)) {
+ return 0;
+ }
+ break;
+ case FINDALLDEVICES:
+ break;
}
return CMP_MATCH | CMP_STOP;
}
-/*! \brief Locate device by name or ip address
+/*!
+ * \brief Locate device by name or ip address
+ *
+ * \param which_objects Define which objects should be matched when doing a lookup
+ * by name. Valid options are FINDUSERS, FINDPEERS, or FINDALLDEVICES.
+ * Note that this option is not used at all when doing a lookup by IP.
+ *
* This is used on find matching device on name or ip/port.
- If the device was declared as type=peer, we don't match on peer name on incoming INVITEs.
-
- \note Avoid using this function in new functions if there is a way to avoid it, i
- since it might cause a database lookup.
-*/
-static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int forcenamematch, int devstate_only)
+ * If the device was declared as type=peer, we don't match on peer name on incoming INVITEs.
+ *
+ * \note Avoid using this function in new functions if there is a way to avoid it,
+ * since it might cause a database lookup.
+ */
+static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int which_objects, int devstate_only)
{
struct sip_peer *p = NULL;
if (peer) {
- struct peer_finding_info pfi = { .forcenamematch = forcenamematch, };
+ struct peer_finding_info pfi = {
+ .which_objects = which_objects,
+ };
ast_copy_string(pfi.tmp_peer.name, peer, sizeof(pfi.tmp_peer.name));
p = ao2_t_callback(peers, OBJ_POINTER, find_by_name, &pfi, "ao2_callback in peers table");
} else if (sin) { /* search by addr? */
@@ -4432,7 +4449,7 @@ static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockadd
dialog->sa.sin_family = AF_INET;
dialog->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */
dialog->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */
- peer = find_peer(peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+ peer = find_peer(peername, NULL, TRUE, FINDPEERS, FALSE);
if (peer) {
int res;
@@ -11200,7 +11217,7 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
ast_string_field_set(p, exten, name);
build_contact(p);
- peer = find_peer(name, NULL, TRUE, FINDALLDEVICES, FALSE);
+ peer = find_peer(name, NULL, TRUE, FINDPEERS, FALSE);
if (!(peer && ast_apply_ha(peer->ha, sin))) {
/* Peer fails ACL check */
if (peer) {
@@ -12086,11 +12103,11 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
peer = find_peer(of, NULL, TRUE, FINDALLDEVICES, FALSE);
} else {
/* First find devices based on username (avoid all type=peer's) */
- peer = find_peer(of, NULL, TRUE, FINDONLYUSERS, FALSE);
+ peer = find_peer(of, NULL, TRUE, FINDUSERS, FALSE);
/* Then find devices based on IP */
if (!peer) {
- peer = find_peer(NULL, &p->recv, TRUE, FINDALLDEVICES, FALSE);
+ peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE);
}
}
@@ -13420,7 +13437,7 @@ static char *_sip_qualify_peer(int type, int fd, struct mansession *s, const str
return CLI_SHOWUSAGE;
load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE;
- if ((peer = find_peer(argv[3], NULL, load_realtime, FINDALLDEVICES, FALSE))) {
+ if ((peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE))) {
sip_poke_peer(peer, 1);
unref_peer(peer, "qualify: done with peer");
} else if (type == 0) {
@@ -13502,7 +13519,8 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
return CLI_SHOWUSAGE;
load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE;
- peer = find_peer(argv[3], NULL, load_realtime, FINDALLDEVICES, FALSE);
+ peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE);
+
if (s) { /* Manager */
if (peer) {
const char *id = astman_get_header(m, "ActionID");
@@ -13780,7 +13798,7 @@ static char *sip_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args
/* Load from realtime storage? */
load_realtime = (a->argc == 5 && !strcmp(a->argv[4], "load")) ? TRUE : FALSE;
- if ((user = find_peer(a->argv[3], NULL, load_realtime, TRUE, FALSE))) {
+ if ((user = find_peer(a->argv[3], NULL, load_realtime, FINDUSERS, FALSE))) {
ao2_lock(user);
ast_cli(a->fd, "\n\n");
ast_cli(a->fd, " * Name : %s\n", user->name);
@@ -13938,7 +13956,7 @@ static char *sip_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
if (a->argc != 3)
return CLI_SHOWUSAGE;
- if ((peer = find_peer(a->argv[2], NULL, load_realtime, FINDALLDEVICES, TRUE))) {
+ if ((peer = find_peer(a->argv[2], NULL, load_realtime, FINDPEERS, TRUE))) {
if (peer->expire > 0) {
expire_register(ref_peer(peer, "ref for expire_register"));
ast_cli(a->fd, "Unregistered peer \'%s\'\n\n", a->argv[2]);
@@ -14910,7 +14928,7 @@ static char *sip_do_debug_ip(int fd, char *arg)
/*! \brief Turn on SIP debugging for a given peer */
static char *sip_do_debug_peer(int fd, char *arg)
{
- struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDALLDEVICES, FALSE);
+ struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDPEERS, FALSE);
if (!peer)
ast_cli(fd, "No such peer '%s'\n", arg);
else if (peer->addr.sin_addr.s_addr == 0)
@@ -15406,7 +15424,7 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat
else
colname = "ip";
- if (!(peer = find_peer(data, NULL, TRUE, FINDALLDEVICES, FALSE)))
+ if (!(peer = find_peer(data, NULL, TRUE, FINDPEERS, FALSE)))
return -1;
if (!strcasecmp(colname, "ip")) {
@@ -20617,7 +20635,7 @@ int st_get_se(struct sip_pvt *p, int max)
if (p->stimer->st_cached_max_se) {
return p->stimer->st_cached_max_se;
} else if (p->peername) {
- struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+ struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
if (pp) {
p->stimer->st_cached_max_se = pp->stimer.st_max_se;
unref_peer(pp, "unref peer pointer from find_peer call in st_get_se");
@@ -20630,7 +20648,7 @@ int st_get_se(struct sip_pvt *p, int max)
if (p->stimer->st_cached_min_se) {
return p->stimer->st_cached_min_se;
} else if (p->peername) {
- struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+ struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
if (pp) {
p->stimer->st_cached_min_se = pp->stimer.st_min_se;
unref_peer(pp, "unref peer pointer from find_peer call in st_get_se (2)");
@@ -20652,7 +20670,7 @@ enum st_refresher st_get_refresher(struct sip_pvt *p)
return p->stimer->st_cached_ref;
if (p->peername) {
- struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+ struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
if (pp) {
p->stimer->st_cached_ref = pp->stimer.st_ref;
unref_peer(pp, "unref peer pointer from find_peer call in st_get_refresher");
@@ -20677,7 +20695,7 @@ enum st_mode st_get_mode(struct sip_pvt *p)
return p->stimer->st_cached_mode;
if (p->peername) {
- struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+ struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
if (pp) {
p->stimer->st_cached_mode = pp->stimer.st_mode_oper;
unref_peer(pp, "unref peer pointer from find_peer call in st_get_mode");
@@ -21507,7 +21525,7 @@ static void add_peer_mailboxes(struct sip_peer *peer, const char *value)
}
/*! \brief Build peer from configuration (file or realtime static/dynamic) */
-static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int ispeer)
+static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
{
struct sip_peer *peer = NULL;
struct ast_ha *oldha = NULL;
@@ -21522,7 +21540,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
const char *srvlookup = NULL;
static int deprecation_warning = 1;
struct ast_str *fullcontact = ast_str_alloca(512);
-
+
if (!realtime || ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
/* Note we do NOT use find_peer here, to avoid realtime recursion */
/* We also use a case-sensitive comparison (unlike find_peer) so
@@ -21532,13 +21550,13 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
ast_copy_string(tmp_peer.name, name, sizeof(tmp_peer.name));
peer = ao2_t_find(peers, &tmp_peer, OBJ_POINTER | OBJ_UNLINK, "find and unlink peer from peers table");
}
-
+
if (peer) {
/* Already in the list, remove it and it will be added back (or FREE'd) */
found++;
if (!(peer->the_mark))
firstpass = 0;
- } else {
+ } else {
if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct")))
return NULL;
@@ -21549,17 +21567,16 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
ast_atomic_fetchadd_int(&speerobjs, 1);
}
- peer->onlymatchonip = ispeer; /* If type=peer, don't match on caller ID for incoming calls */
-
/* Note that our peer HAS had its reference count increased */
if (firstpass) {
peer->lastmsgssent = -1;
oldha = peer->ha;
peer->ha = NULL;
set_peer_defaults(peer); /* Set peer defaults */
+ peer->type = 0;
}
if (!found && name)
- ast_copy_string(peer->name, name, sizeof(peer->name));
+ ast_copy_string(peer->name, name, sizeof(peer->name));
/* If we have channel variables, remove them (reload) */
if (peer->chanvars) {
@@ -21613,13 +21630,10 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
}
} else if (!strcasecmp(v->name, "type")) {
if (!strcasecmp(v->value, "peer")) {
- peer->onlymatchonip = TRUE; /* For realtime support, add type=peer in the table */
- peer->type = SIP_TYPE_PEER;
+ peer->type |= SIP_TYPE_PEER;
} else if (!strcasecmp(v->value, "user")) {
- peer->onlymatchonip = FALSE;
- peer->type = SIP_TYPE_USER;
+ peer->type |= SIP_TYPE_USER;
} else if (!strcasecmp(v->value, "friend")) {
- peer->onlymatchonip = FALSE;
peer->type = SIP_TYPE_USER | SIP_TYPE_PEER;
}
} else if (!strcasecmp(v->name, "secret"))
@@ -22618,10 +22632,10 @@ static int reload_config(enum channelreloadreason reason)
hassip = ast_variable_retrieve(ucfg, cat, "hassip");
registersip = ast_variable_retrieve(ucfg, cat, "registersip");
if (ast_true(hassip) || (!hassip && genhassip)) {
- peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0, FALSE);
+ peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
if (peer) {
ao2_t_link(peers, peer, "link peer into peer table");
- if (peer->addr.sin_addr.s_addr) {
+ if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) {
ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
}
@@ -22670,27 +22684,24 @@ static int reload_config(enum channelreloadreason reason)
ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
continue;
} else {
- int is_peer = 0;
if (!strcasecmp(utype, "user")) {
- is_peer = 1;
+ ;
} else if (!strcasecmp(utype, "friend")) {
- is_peer = 1;
- } else if (!strcasecmp(utype, "peer"))
- is_peer = 2;
- else {
+ ;
+ } else if (!strcasecmp(utype, "peer")) {
+ ;
+ } else {
ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, "sip.conf");
continue;
}
- if (is_peer) {
- peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0, is_peer == 2);
- if (peer) {
- ao2_t_link(peers, peer, "link peer into peers table");
- if (peer->addr.sin_addr.s_addr) {
- ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
- }
- unref_peer(peer, "unref the result of the build_peer call. Now, the links from the tables are the only ones left.");
- peer_count++;
+ peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
+ if (peer) {
+ ao2_t_link(peers, peer, "link peer into peers table");
+ if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) {
+ ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
}
+ unref_peer(peer, "unref the result of the build_peer call. Now, the links from the tables are the only ones left.");
+ peer_count++;
}
}
}