|
|
|
@ -2063,7 +2063,7 @@ 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);
|
|
|
|
|
static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int forcenamematch, 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);
|
|
|
|
@ -2076,7 +2076,7 @@ static void realtime_update_peer(const char *peername, struct sockaddr_in *sin,
|
|
|
|
|
static void update_peer(struct sip_peer *p, int expire);
|
|
|
|
|
static struct ast_variable *get_insecure_variable_from_config(struct ast_config *config);
|
|
|
|
|
static const char *get_name_from_variable(struct ast_variable *var, const char *newpeername);
|
|
|
|
|
static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in *sin);
|
|
|
|
|
static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in *sin, int devstate_only);
|
|
|
|
|
static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
|
|
|
|
|
|
|
|
|
|
/*--- Internal UA client handling (outbound registrations) */
|
|
|
|
@ -3856,7 +3856,7 @@ static const char *get_name_from_variable(struct ast_variable *var, const char *
|
|
|
|
|
* This returns a pointer to a peer and because we use build_peer, we can rest
|
|
|
|
|
* assured that the refcount is bumped.
|
|
|
|
|
*/
|
|
|
|
|
static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_in *sin)
|
|
|
|
|
static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_in *sin, int devstate_only)
|
|
|
|
|
{
|
|
|
|
|
struct sip_peer *peer;
|
|
|
|
|
struct ast_variable *var = NULL;
|
|
|
|
@ -4015,7 +4015,7 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
|
|
|
|
|
|
|
|
|
|
ast_debug(3, "-REALTIME- loading peer from database to memory. Name: %s. Peer objects: %d\n", peer->name, rpeerobjs);
|
|
|
|
|
|
|
|
|
|
if (ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
|
|
|
|
|
if (ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) && !devstate_only) {
|
|
|
|
|
/* Cache peer */
|
|
|
|
|
ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_RTAUTOCLEAR|SIP_PAGE2_RTCACHEFRIENDS);
|
|
|
|
|
if (ast_test_flag(&global_flags[1], SIP_PAGE2_RTAUTOCLEAR)) {
|
|
|
|
@ -4046,7 +4046,7 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
|
|
|
|
|
\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)
|
|
|
|
|
static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int forcenamematch, int devstate_only)
|
|
|
|
|
{
|
|
|
|
|
struct sip_peer *p = NULL;
|
|
|
|
|
struct sip_peer tmp_peer;
|
|
|
|
@ -4068,8 +4068,8 @@ static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!p && realtime)
|
|
|
|
|
p = realtime_peer(peer, sin);
|
|
|
|
|
if (!p && (realtime || devstate_only))
|
|
|
|
|
p = realtime_peer(peer, sin, devstate_only);
|
|
|
|
|
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
@ -4318,7 +4318,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, TRUE);
|
|
|
|
|
peer = find_peer(peername, NULL, TRUE, TRUE, FALSE);
|
|
|
|
|
|
|
|
|
|
if (peer) {
|
|
|
|
|
int res;
|
|
|
|
@ -4664,7 +4664,7 @@ static int update_call_counter(struct sip_pvt *fup, int event)
|
|
|
|
|
ast_copy_string(name, fup->username, sizeof(name));
|
|
|
|
|
|
|
|
|
|
/* Check the list of devices */
|
|
|
|
|
if ( (p = find_peer(ast_strlen_zero(fup->peername) ? name : fup->peername, NULL, TRUE, FALSE) ) ) { /* Try to find peer */
|
|
|
|
|
if ( (p = find_peer(ast_strlen_zero(fup->peername) ? name : fup->peername, NULL, TRUE, FALSE, FALSE) ) ) { /* Try to find peer */
|
|
|
|
|
inuse = &p->inUse;
|
|
|
|
|
call_limit = &p->call_limit;
|
|
|
|
|
inringing = &p->inRinging;
|
|
|
|
@ -10184,8 +10184,7 @@ static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Change the other partys IP address based on given contact */
|
|
|
|
|
static int set_address_from_contact(struct sip_pvt *pvt)
|
|
|
|
|
static int __set_address_from_contact(const char *fullcontact, struct sockaddr_in *sin, int tcp)
|
|
|
|
|
{
|
|
|
|
|
struct hostent *hp;
|
|
|
|
|
struct ast_hostent ahp;
|
|
|
|
@ -10195,22 +10194,14 @@ static int set_address_from_contact(struct sip_pvt *pvt)
|
|
|
|
|
char contact2_buf[256];
|
|
|
|
|
char *contact, *contact2;
|
|
|
|
|
|
|
|
|
|
if (ast_test_flag(&pvt->flags[0], SIP_NAT_ROUTE)) {
|
|
|
|
|
/* NAT: Don't trust the contact field. Just use what they came to us
|
|
|
|
|
with. */
|
|
|
|
|
pvt->sa = pvt->recv;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Work on a copy */
|
|
|
|
|
ast_copy_string(contact_buf, pvt->fullcontact, sizeof(contact_buf));
|
|
|
|
|
ast_copy_string(contact2_buf, pvt->fullcontact, sizeof(contact2_buf));
|
|
|
|
|
ast_copy_string(contact_buf, fullcontact, sizeof(contact_buf));
|
|
|
|
|
ast_copy_string(contact2_buf, fullcontact, sizeof(contact2_buf));
|
|
|
|
|
contact = contact_buf;
|
|
|
|
|
contact2 = contact2_buf;
|
|
|
|
|
|
|
|
|
|
/* We have only the part in <brackets> here so we just need to parse a SIP URI.*/
|
|
|
|
|
|
|
|
|
|
if (pvt->socket.type == SIP_TRANSPORT_TLS) {
|
|
|
|
|
if (tcp) {
|
|
|
|
|
if (parse_uri(contact, "sips:", &contact, NULL, &host, &pt, NULL)) {
|
|
|
|
|
if (parse_uri(contact2, "sip:", &contact, NULL, &host, &pt, NULL))
|
|
|
|
|
ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", contact);
|
|
|
|
@ -10222,10 +10213,6 @@ static int set_address_from_contact(struct sip_pvt *pvt)
|
|
|
|
|
port = !ast_strlen_zero(pt) ? atoi(pt) : STANDARD_SIP_PORT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sip_debug_test_pvt(pvt)) {
|
|
|
|
|
ast_verbose("--- set_address_from_contact host '%s'\n", host);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX This could block for a long time XXX */
|
|
|
|
|
/* We should only do this if it's a name, not an IP */
|
|
|
|
|
hp = ast_gethostbyname(host, &ahp);
|
|
|
|
@ -10233,13 +10220,26 @@ static int set_address_from_contact(struct sip_pvt *pvt)
|
|
|
|
|
ast_log(LOG_WARNING, "Invalid host name in Contact: (can't resolve in DNS) : '%s'\n", host);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
pvt->sa.sin_family = AF_INET;
|
|
|
|
|
memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
|
|
|
|
|
pvt->sa.sin_port = htons(port);
|
|
|
|
|
sin->sin_family = AF_INET;
|
|
|
|
|
memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
|
|
|
|
|
sin->sin_port = htons(port);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Change the other partys IP address based on given contact */
|
|
|
|
|
static int set_address_from_contact(struct sip_pvt *pvt)
|
|
|
|
|
{
|
|
|
|
|
if (ast_test_flag(&pvt->flags[0], SIP_NAT_ROUTE)) {
|
|
|
|
|
/* NAT: Don't trust the contact field. Just use what they came to us
|
|
|
|
|
with. */
|
|
|
|
|
pvt->sa = pvt->recv;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return __set_address_from_contact(pvt->fullcontact, &pvt->sa, pvt->socket.type == SIP_TRANSPORT_TLS ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! \brief Parse contact header and save registration (peer registration) */
|
|
|
|
|
static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *peer, struct sip_request *req)
|
|
|
|
@ -10693,7 +10693,7 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *
|
|
|
|
|
/*! \brief Change onhold state of a peer using a pvt structure */
|
|
|
|
|
static void sip_peer_hold(struct sip_pvt *p, int hold)
|
|
|
|
|
{
|
|
|
|
|
struct sip_peer *peer = find_peer(p->peername, NULL, 1, TRUE);
|
|
|
|
|
struct sip_peer *peer = find_peer(p->peername, NULL, 1, TRUE, FALSE);
|
|
|
|
|
|
|
|
|
|
if (!peer)
|
|
|
|
|
return;
|
|
|
|
@ -10842,7 +10842,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, TRUE);
|
|
|
|
|
peer = find_peer(name, NULL, TRUE, TRUE, FALSE);
|
|
|
|
|
if (!(peer && ast_apply_ha(peer->ha, sin))) {
|
|
|
|
|
/* Peer fails ACL check */
|
|
|
|
|
if (peer) {
|
|
|
|
@ -11718,11 +11718,11 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
|
|
|
|
|
* match on IP address-port of the incoming request.
|
|
|
|
|
*/
|
|
|
|
|
/* First find device on name */
|
|
|
|
|
peer = find_peer(of, NULL, TRUE, FALSE);
|
|
|
|
|
peer = find_peer(of, NULL, TRUE, FALSE, FALSE);
|
|
|
|
|
|
|
|
|
|
/* If not found, then find device on IP (if it's not a SUBSCRIBE) */
|
|
|
|
|
if (!peer && sipmethod != SIP_SUBSCRIBE) {
|
|
|
|
|
peer = find_peer(NULL, &p->recv, TRUE, FALSE);
|
|
|
|
|
peer = find_peer(NULL, &p->recv, TRUE, FALSE, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!peer) {
|
|
|
|
@ -12970,7 +12970,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, FALSE))) {
|
|
|
|
|
if ((peer = find_peer(argv[3], NULL, load_realtime, FALSE, FALSE))) {
|
|
|
|
|
sip_poke_peer(peer, 1);
|
|
|
|
|
unref_peer(peer, "qualify: done with peer");
|
|
|
|
|
} else if (type == 0) {
|
|
|
|
@ -13052,7 +13052,7 @@ 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, TRUE);
|
|
|
|
|
peer = find_peer(argv[3], NULL, load_realtime, TRUE, FALSE);
|
|
|
|
|
if (s) { /* Manager */
|
|
|
|
|
if (peer) {
|
|
|
|
|
const char *id = astman_get_header(m, "ActionID");
|
|
|
|
@ -13374,7 +13374,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, TRUE))) {
|
|
|
|
|
if ((peer = find_peer(a->argv[2], NULL, load_realtime, TRUE, TRUE))) {
|
|
|
|
|
if (peer->expire > 0) {
|
|
|
|
|
expire_register(peer);
|
|
|
|
|
ast_cli(a->fd, "Unregistered peer \'%s\'\n\n", a->argv[2]);
|
|
|
|
@ -14346,7 +14346,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, TRUE);
|
|
|
|
|
struct sip_peer *peer = find_peer(arg, NULL, TRUE, TRUE, FALSE);
|
|
|
|
|
if (!peer)
|
|
|
|
|
ast_cli(fd, "No such peer '%s'\n", arg);
|
|
|
|
|
else if (peer->addr.sin_addr.s_addr == 0)
|
|
|
|
@ -14842,7 +14842,7 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat
|
|
|
|
|
else
|
|
|
|
|
colname = "ip";
|
|
|
|
|
|
|
|
|
|
if (!(peer = find_peer(data, NULL, TRUE, TRUE)))
|
|
|
|
|
if (!(peer = find_peer(data, NULL, TRUE, TRUE, FALSE)))
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if (!strcasecmp(colname, "ip")) {
|
|
|
|
@ -19823,7 +19823,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, TRUE);
|
|
|
|
|
struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, TRUE, 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");
|
|
|
|
@ -19836,7 +19836,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, TRUE);
|
|
|
|
|
struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, TRUE, 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)");
|
|
|
|
@ -19858,7 +19858,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, TRUE);
|
|
|
|
|
struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, TRUE, 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");
|
|
|
|
@ -19883,7 +19883,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, TRUE);
|
|
|
|
|
struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, TRUE, 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");
|
|
|
|
@ -20055,7 +20055,7 @@ static int sip_devicestate(void *data)
|
|
|
|
|
* load it BACK into memory, thus defeating the point of trying to clear dead
|
|
|
|
|
* hosts out of memory.
|
|
|
|
|
*/
|
|
|
|
|
if ((p = find_peer(host, NULL, FALSE, TRUE))) {
|
|
|
|
|
if ((p = find_peer(host, NULL, FALSE, TRUE, TRUE))) {
|
|
|
|
|
if (p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) {
|
|
|
|
|
/* we have an address for the peer */
|
|
|
|
|
|
|
|
|
@ -21045,6 +21045,14 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
|
|
|
|
|
if (fullcontact->used > 0) {
|
|
|
|
|
ast_copy_string(peer->fullcontact, fullcontact->str, sizeof(peer->fullcontact));
|
|
|
|
|
peer->rt_fromcontact = TRUE;
|
|
|
|
|
/* We have a hostname in the fullcontact, but if we don't have an
|
|
|
|
|
* address listed on the entry (or if it's 'dynamic'), then we need to
|
|
|
|
|
* parse the entry to obtain the IP address, so a dynamic host can be
|
|
|
|
|
* contacted immediately after reload (as opposed to waiting for it to
|
|
|
|
|
* register once again). */
|
|
|
|
|
/* XXX May need to revisit the final argument; does the realtime DB store whether
|
|
|
|
|
* the original contact was over TLS or not? XXX */
|
|
|
|
|
__set_address_from_contact(fullcontact->str, &peer->addr, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (srvlookup && peer->dnsmgr == NULL) {
|
|
|
|
|