diff options
-rw-r--r-- | channels/chan_sip.c | 132 |
1 files changed, 70 insertions, 62 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 6051fa9ec..dfde185c5 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -487,8 +487,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #endif /* Arguments for find_peer */ -#define FINDALLDEVICES FALSE -#define FINDONLYUSERS TRUE +#define FINDUSERS (1 << 0) +#define FINDPEERS (1 << 1) +#define FINDALLDEVICES (FINDUSERS | FINDPEERS) #define SIPBUFSIZE 512 /*!< Buffer size for many operations */ @@ -1898,7 +1899,6 @@ struct sip_peer { /*XXX Seems like we suddenly have two flags with the same content. Why? To be continued... */ enum sip_peer_type type; /*!< Distinguish between "user" and "peer" types. This is used solely for CLI and manager commands */ - char onlymatchonip; /*!< Only match on IP for incoming calls (old type=peer) */ }; @@ -2438,7 +2438,7 @@ 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); @@ -4471,7 +4471,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); @@ -4513,38 +4513,52 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i static int find_by_name(void *obj, void *arg, void *data, int flags) { struct sip_peer *search = obj, *match = arg; - int *forcenamematch = data; + int *which_objects = data; /* Usernames in SIP uri's are case sensitive. Domains are not */ if (strcmp(search->name, match->name)) { 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 (*forcenamematch && search->onlymatchonip) { - return 0; + switch (*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, - 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; struct sip_peer tmp_peer; if (peer) { ast_copy_string(tmp_peer.name, peer, sizeof(tmp_peer.name)); - p = ao2_t_callback_data(peers, OBJ_POINTER, find_by_name, &tmp_peer, &forcenamematch, "ao2_find in peers table"); + p = ao2_t_callback_data(peers, OBJ_POINTER, find_by_name, &tmp_peer, &which_objects, "ao2_find in peers table"); } else if (sin) { /* search by addr? */ tmp_peer.addr.sin_addr.s_addr = sin->sin_addr.s_addr; tmp_peer.addr.sin_port = sin->sin_port; @@ -4839,7 +4853,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; @@ -11972,7 +11986,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) { @@ -12884,11 +12898,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); } } @@ -14226,7 +14240,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) { @@ -14308,7 +14322,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"); @@ -14590,7 +14605,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); @@ -14748,7 +14763,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]); @@ -15758,7 +15773,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) @@ -16213,7 +16228,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")) { @@ -21571,7 +21586,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"); @@ -21584,7 +21599,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)"); @@ -21606,7 +21621,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"); @@ -21631,7 +21646,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"); @@ -22473,7 +22488,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; @@ -22488,7 +22503,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 @@ -22498,13 +22513,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; @@ -22520,17 +22535,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) { @@ -22584,13 +22598,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, "remotesecret")) { @@ -23667,10 +23678,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"); } @@ -23719,27 +23730,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++; } } } |