diff options
-rw-r--r-- | channels/chan_sip.c | 135 |
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++; } } } |