|
|
|
@ -242,7 +242,7 @@ struct dundi_precache_queue {
|
|
|
|
|
struct dundi_request;
|
|
|
|
|
|
|
|
|
|
struct dundi_transaction {
|
|
|
|
|
struct sockaddr_in addr; /*!< Other end of transaction */
|
|
|
|
|
struct ast_sockaddr addr; /*!< Other end of transaction */
|
|
|
|
|
struct timeval start; /*!< When this transaction was created */
|
|
|
|
|
dundi_eid eids[DUNDI_MAX_STACK + 1];
|
|
|
|
|
int eidcount; /*!< Number of eids in eids */
|
|
|
|
@ -301,7 +301,7 @@ struct dundi_mapping {
|
|
|
|
|
|
|
|
|
|
struct dundi_peer {
|
|
|
|
|
dundi_eid eid;
|
|
|
|
|
struct sockaddr_in addr; /*!< Address of DUNDi peer */
|
|
|
|
|
struct ast_sockaddr addr; /*!< Address of DUNDi peer */
|
|
|
|
|
AST_LIST_HEAD_NOLOCK(permissionlist, permission) permit;
|
|
|
|
|
struct permissionlist include;
|
|
|
|
|
dundi_eid us_eid;
|
|
|
|
@ -407,18 +407,20 @@ static int str2tech(char *str)
|
|
|
|
|
static int dundi_lookup_internal(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int ttl, int blockempty, struct dundi_hint_metadata *md, int *expiration, int cybpass, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int direct[]);
|
|
|
|
|
static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[]);
|
|
|
|
|
static struct dundi_transaction *create_transaction(struct dundi_peer *p);
|
|
|
|
|
static struct dundi_transaction *find_transaction(struct dundi_hdr *hdr, struct sockaddr_in *sin)
|
|
|
|
|
|
|
|
|
|
static struct dundi_transaction *find_transaction(struct dundi_hdr *hdr, struct ast_sockaddr *sin)
|
|
|
|
|
{
|
|
|
|
|
struct dundi_transaction *trans;
|
|
|
|
|
|
|
|
|
|
/* Look for an exact match first */
|
|
|
|
|
AST_LIST_TRAVERSE(&alltrans, trans, all) {
|
|
|
|
|
if (!inaddrcmp(&trans->addr, sin) &&
|
|
|
|
|
((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ ||
|
|
|
|
|
((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) {
|
|
|
|
|
if (hdr->strans)
|
|
|
|
|
trans->dtrans = ntohs(hdr->strans) & 32767;
|
|
|
|
|
return trans;
|
|
|
|
|
if (!ast_sockaddr_cmp(&trans->addr, sin) &&
|
|
|
|
|
((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ ||
|
|
|
|
|
((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) {
|
|
|
|
|
if (hdr->strans) {
|
|
|
|
|
trans->dtrans = ntohs(hdr->strans) & 32767;
|
|
|
|
|
}
|
|
|
|
|
return trans;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -434,7 +436,7 @@ static struct dundi_transaction *find_transaction(struct dundi_hdr *hdr, struct
|
|
|
|
|
/* Create new transaction */
|
|
|
|
|
if (!(trans = create_transaction(NULL)))
|
|
|
|
|
break;
|
|
|
|
|
memcpy(&trans->addr, sin, sizeof(trans->addr));
|
|
|
|
|
ast_sockaddr_copy(&trans->addr, sin);
|
|
|
|
|
trans->dtrans = ntohs(hdr->strans) & 32767;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
@ -449,7 +451,7 @@ static int dundi_ack(struct dundi_transaction *trans, int final)
|
|
|
|
|
{
|
|
|
|
|
return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL);
|
|
|
|
|
}
|
|
|
|
|
static void dundi_reject(struct dundi_hdr *h, struct sockaddr_in *sin)
|
|
|
|
|
static void dundi_reject(struct dundi_hdr *h, struct ast_sockaddr *sin)
|
|
|
|
|
{
|
|
|
|
|
struct {
|
|
|
|
|
struct dundi_packet pack;
|
|
|
|
@ -461,7 +463,7 @@ static void dundi_reject(struct dundi_hdr *h, struct sockaddr_in *sin)
|
|
|
|
|
return;
|
|
|
|
|
memset(&tmp, 0, sizeof(tmp));
|
|
|
|
|
memset(&trans, 0, sizeof(trans));
|
|
|
|
|
memcpy(&trans.addr, sin, sizeof(trans.addr));
|
|
|
|
|
ast_sockaddr_copy(&trans.addr, sin);
|
|
|
|
|
tmp.hdr.strans = h->dtrans;
|
|
|
|
|
tmp.hdr.dtrans = h->strans;
|
|
|
|
|
tmp.hdr.iseqno = h->oseqno;
|
|
|
|
@ -1291,8 +1293,9 @@ static void qualify_peer(struct dundi_peer *peer, int schedonly);
|
|
|
|
|
|
|
|
|
|
static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)
|
|
|
|
|
{
|
|
|
|
|
if (!trans->addr.sin_addr.s_addr)
|
|
|
|
|
memcpy(&trans->addr, &p->addr, sizeof(trans->addr));
|
|
|
|
|
if (ast_sockaddr_isnull(&trans->addr)) {
|
|
|
|
|
ast_sockaddr_copy(&trans->addr, &p->addr);
|
|
|
|
|
}
|
|
|
|
|
trans->us_eid = p->us_eid;
|
|
|
|
|
trans->them_eid = p->eid;
|
|
|
|
|
/* Enable encryption if appropriate */
|
|
|
|
@ -1323,7 +1326,7 @@ static int do_register_expire(const void *data)
|
|
|
|
|
ast_db_del("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid));
|
|
|
|
|
peer->registerexpire = -1;
|
|
|
|
|
peer->lastms = 0;
|
|
|
|
|
memset(&peer->addr, 0, sizeof(peer->addr));
|
|
|
|
|
ast_sockaddr_setnull(&peer->addr);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1719,17 +1722,16 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
|
|
|
|
|
int needqual = 0;
|
|
|
|
|
AST_SCHED_DEL(sched, peer->registerexpire);
|
|
|
|
|
peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
|
|
|
|
|
snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(trans->addr.sin_addr),
|
|
|
|
|
ntohs(trans->addr.sin_port), expire);
|
|
|
|
|
snprintf(data, sizeof(data), "%s:%d", ast_sockaddr_stringify(&trans->addr), expire);
|
|
|
|
|
ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data);
|
|
|
|
|
if (inaddrcmp(&peer->addr, &trans->addr)) {
|
|
|
|
|
ast_verb(3, "Registered DUNDi peer '%s' at '%s:%d'\n",
|
|
|
|
|
ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
|
|
|
|
|
ast_inet_ntoa(trans->addr.sin_addr), ntohs(trans->addr.sin_port));
|
|
|
|
|
if (ast_sockaddr_cmp(&peer->addr, &trans->addr)) {
|
|
|
|
|
ast_verb(3, "Registered DUNDi peer '%s' at '%s'\n",
|
|
|
|
|
ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
|
|
|
|
|
ast_sockaddr_stringify(&trans->addr));
|
|
|
|
|
needqual = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(&peer->addr, &trans->addr, sizeof(peer->addr));
|
|
|
|
|
ast_sockaddr_copy(&peer->addr, &trans->addr);
|
|
|
|
|
dundi_ie_append_short(ied, DUNDI_IE_EXPIRATION, default_expiration);
|
|
|
|
|
dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied);
|
|
|
|
|
if (needqual)
|
|
|
|
@ -1853,7 +1855,7 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
|
|
|
|
|
ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr));
|
|
|
|
|
if (!ast_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) {
|
|
|
|
|
/* If it's them, update our address */
|
|
|
|
|
ast_copy_string(trans->parent->dei->ipaddr, ast_inet_ntoa(trans->addr.sin_addr), sizeof(trans->parent->dei->ipaddr));
|
|
|
|
|
ast_copy_string(trans->parent->dei->ipaddr, ast_sockaddr_stringify_addr(&trans->addr), sizeof(trans->parent->dei->ipaddr));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ies.hint) {
|
|
|
|
@ -2036,7 +2038,7 @@ static int ack_trans(struct dundi_transaction *trans, int iseqno)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int handle_frame(struct dundi_hdr *h, struct sockaddr_in *sin, int datalen)
|
|
|
|
|
static int handle_frame(struct dundi_hdr *h, struct ast_sockaddr *sin, int datalen)
|
|
|
|
|
{
|
|
|
|
|
struct dundi_transaction *trans;
|
|
|
|
|
trans = find_transaction(h, sin);
|
|
|
|
@ -2079,13 +2081,12 @@ static int handle_frame(struct dundi_hdr *h, struct sockaddr_in *sin, int datale
|
|
|
|
|
|
|
|
|
|
static int socket_read(int *id, int fd, short events, void *cbdata)
|
|
|
|
|
{
|
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
|
struct ast_sockaddr sin;
|
|
|
|
|
int res;
|
|
|
|
|
struct dundi_hdr *h;
|
|
|
|
|
char buf[MAX_PACKET_SIZE];
|
|
|
|
|
socklen_t len = sizeof(sin);
|
|
|
|
|
|
|
|
|
|
res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin, &len);
|
|
|
|
|
res = ast_recvfrom(netsocket, buf, sizeof(buf), 0, &sin);
|
|
|
|
|
if (res < 0) {
|
|
|
|
|
if (errno != ECONNREFUSED)
|
|
|
|
|
ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
|
|
|
|
@ -2588,6 +2589,26 @@ static char *dundi_do_query(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
|
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *dundi_sockaddr_stringify_host(const struct ast_sockaddr *addr)
|
|
|
|
|
{
|
|
|
|
|
if (ast_sockaddr_isnull(addr)) {
|
|
|
|
|
return "(Unspecified)";
|
|
|
|
|
}
|
|
|
|
|
return ast_sockaddr_stringify_host(addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint16_t dundi_sockaddr_port(const struct ast_sockaddr *addr)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Test to avoid a debug message complaining about addr
|
|
|
|
|
* not being an IPv4 or IPv6 address.
|
|
|
|
|
*/
|
|
|
|
|
if (ast_sockaddr_isnull(addr)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return ast_sockaddr_port(addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *dundi_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
|
{
|
|
|
|
|
struct dundi_peer *peer;
|
|
|
|
@ -2633,8 +2654,8 @@ static char *dundi_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
|
|
|
|
|
ast_cli(a->fd, "Peer: %s\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
|
|
|
|
|
ast_cli(a->fd, "Model: %s\n", model2str(peer->model));
|
|
|
|
|
ast_cli(a->fd, "Order: %s\n", order);
|
|
|
|
|
ast_cli(a->fd, "Host: %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "<Unspecified>");
|
|
|
|
|
ast_cli(a->fd, "Port: %d\n", ntohs(peer->addr.sin_port));
|
|
|
|
|
ast_cli(a->fd, "Host: %s\n", ast_sockaddr_isnull(&peer->addr) ? "<Unspecified>" : ast_sockaddr_stringify_host(&peer->addr));
|
|
|
|
|
ast_cli(a->fd, "Port: %d\n", dundi_sockaddr_port(&peer->addr));
|
|
|
|
|
ast_cli(a->fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");
|
|
|
|
|
ast_cli(a->fd, "Reg: %s\n", peer->registerid < 0 ? "No" : "Yes");
|
|
|
|
|
ast_cli(a->fd, "In Key: %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey);
|
|
|
|
@ -2666,8 +2687,8 @@ static char *dundi_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
|
|
|
|
|
|
|
|
|
|
static char *dundi_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
|
{
|
|
|
|
|
#define FORMAT2 "%-20.20s %-15.15s %-6.6s %-10.10s %-8.8s %-15.15s\n"
|
|
|
|
|
#define FORMAT "%-20.20s %-15.15s %s %-6d %-10.10s %-8.8s %-15.15s\n"
|
|
|
|
|
#define FORMAT2 "%-20.20s %-41s %-6.6s %-10.10s %-8.8s %-15.15s\n"
|
|
|
|
|
#define FORMAT "%-20.20s %-41s %s %-6d %-10.10s %-8.8s %-15.15s\n"
|
|
|
|
|
struct dundi_peer *peer;
|
|
|
|
|
int registeredonly=0;
|
|
|
|
|
char avgms[20];
|
|
|
|
@ -2704,9 +2725,11 @@ static char *dundi_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_a
|
|
|
|
|
char status[20];
|
|
|
|
|
int print_line = -1;
|
|
|
|
|
char srch[2000];
|
|
|
|
|
|
|
|
|
|
total_peers++;
|
|
|
|
|
if (registeredonly && !peer->addr.sin_addr.s_addr)
|
|
|
|
|
if (registeredonly && ast_sockaddr_isnull(&peer->addr)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (peer->maxms) {
|
|
|
|
|
if (peer->lastms < 0) {
|
|
|
|
|
strcpy(status, "UNREACHABLE");
|
|
|
|
@ -2732,9 +2755,9 @@ static char *dundi_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_a
|
|
|
|
|
snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms);
|
|
|
|
|
else
|
|
|
|
|
strcpy(avgms, "Unavail");
|
|
|
|
|
snprintf(srch, sizeof(srch), FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
|
|
|
|
|
peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
|
|
|
|
|
peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.sin_port), model2str(peer->model), avgms, status);
|
|
|
|
|
snprintf(srch, sizeof(srch), FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str),
|
|
|
|
|
&peer->eid), dundi_sockaddr_stringify_host(&peer->addr),
|
|
|
|
|
peer->dynamic ? "(D)" : "(S)", dundi_sockaddr_port(&peer->addr), model2str(peer->model), avgms, status);
|
|
|
|
|
|
|
|
|
|
if (a->argc == 5) {
|
|
|
|
|
if (!strcasecmp(a->argv[3],"include") && strstr(srch,a->argv[4])) {
|
|
|
|
@ -2750,8 +2773,8 @@ static char *dundi_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_a
|
|
|
|
|
|
|
|
|
|
if (print_line) {
|
|
|
|
|
ast_cli(a->fd, FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
|
|
|
|
|
peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
|
|
|
|
|
peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.sin_port), model2str(peer->model), avgms, status);
|
|
|
|
|
dundi_sockaddr_stringify_host(&peer->addr),
|
|
|
|
|
peer->dynamic ? "(D)" : "(S)", dundi_sockaddr_port(&peer->addr), model2str(peer->model), avgms, status);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ast_cli(a->fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);
|
|
|
|
@ -2763,8 +2786,8 @@ static char *dundi_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_a
|
|
|
|
|
|
|
|
|
|
static char *dundi_show_trans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
|
{
|
|
|
|
|
#define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
|
|
|
|
|
#define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
|
|
|
|
|
#define FORMAT2 "%-47s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
|
|
|
|
|
#define FORMAT "%-41s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
|
|
|
|
|
struct dundi_transaction *trans;
|
|
|
|
|
switch (cmd) {
|
|
|
|
|
case CLI_INIT:
|
|
|
|
@ -2782,8 +2805,9 @@ static char *dundi_show_trans(struct ast_cli_entry *e, int cmd, struct ast_cli_a
|
|
|
|
|
AST_LIST_LOCK(&peers);
|
|
|
|
|
ast_cli(a->fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack");
|
|
|
|
|
AST_LIST_TRAVERSE(&alltrans, trans, all) {
|
|
|
|
|
ast_cli(a->fd, FORMAT, ast_inet_ntoa(trans->addr.sin_addr),
|
|
|
|
|
ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno);
|
|
|
|
|
ast_cli(a->fd, FORMAT, ast_sockaddr_stringify_host(&trans->addr),
|
|
|
|
|
ast_sockaddr_port(&trans->addr), trans->strans, trans->dtrans,
|
|
|
|
|
trans->oseqno, trans->iseqno, trans->aseqno);
|
|
|
|
|
}
|
|
|
|
|
AST_LIST_UNLOCK(&peers);
|
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
@ -3103,8 +3127,9 @@ static struct dundi_transaction *create_transaction(struct dundi_peer *p)
|
|
|
|
|
int tid;
|
|
|
|
|
|
|
|
|
|
/* Don't allow creation of transactions to non-registered peers */
|
|
|
|
|
if (p && !p->addr.sin_addr.s_addr)
|
|
|
|
|
if (p && ast_sockaddr_isnull(&p->addr)) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
tid = get_trans_id();
|
|
|
|
|
if (tid < 1)
|
|
|
|
|
return NULL;
|
|
|
|
@ -3133,11 +3158,10 @@ static int dundi_xmit(struct dundi_packet *pack)
|
|
|
|
|
int res;
|
|
|
|
|
if (dundidebug)
|
|
|
|
|
dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr));
|
|
|
|
|
res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, sizeof(pack->parent->addr));
|
|
|
|
|
res = ast_sendto(netsocket, pack->data, pack->datalen, 0, &pack->parent->addr);
|
|
|
|
|
if (res < 0) {
|
|
|
|
|
ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n",
|
|
|
|
|
ast_inet_ntoa(pack->parent->addr.sin_addr),
|
|
|
|
|
ntohs(pack->parent->addr.sin_port), strerror(errno));
|
|
|
|
|
ast_log(LOG_WARNING, "Failed to transmit to '%s': %s\n",
|
|
|
|
|
ast_sockaddr_stringify(&pack->parent->addr), strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
if (res > 0)
|
|
|
|
|
res = 0;
|
|
|
|
@ -3242,10 +3266,10 @@ static int dundi_rexmit(const void *data)
|
|
|
|
|
AST_LIST_LOCK(&peers);
|
|
|
|
|
if (pack->retrans < 1) {
|
|
|
|
|
pack->retransid = -1;
|
|
|
|
|
if (!ast_test_flag(pack->parent, FLAG_ISQUAL))
|
|
|
|
|
ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n",
|
|
|
|
|
ast_inet_ntoa(pack->parent->addr.sin_addr),
|
|
|
|
|
ntohs(pack->parent->addr.sin_port), pack->h->oseqno, ntohs(pack->h->strans));
|
|
|
|
|
if (!ast_test_flag(pack->parent, FLAG_ISQUAL)) {
|
|
|
|
|
ast_log(LOG_NOTICE, "Max retries exceeded to host '%s' msg %d on call %d\n",
|
|
|
|
|
ast_sockaddr_stringify(&pack->parent->addr), pack->h->oseqno, ntohs(pack->h->strans));
|
|
|
|
|
}
|
|
|
|
|
destroy_trans(pack->parent, 1);
|
|
|
|
|
res = 0;
|
|
|
|
|
} else {
|
|
|
|
@ -3600,8 +3624,9 @@ static int append_transaction(struct dundi_request *dr, struct dundi_peer *p, in
|
|
|
|
|
char eid_str2[20];
|
|
|
|
|
|
|
|
|
|
/* Ignore if not registered */
|
|
|
|
|
if (!p->addr.sin_addr.s_addr)
|
|
|
|
|
if (ast_sockaddr_isnull(&p->addr)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms)))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
@ -4546,15 +4571,31 @@ static void populate_addr(struct dundi_peer *peer, dundi_eid *eid)
|
|
|
|
|
char eid_str[20];
|
|
|
|
|
ast_eid_to_str(eid_str, sizeof(eid_str), eid);
|
|
|
|
|
if (!ast_db_get("dundi/dpeers", eid_str, data, sizeof(data))) {
|
|
|
|
|
c = strchr(data, ':');
|
|
|
|
|
/*
|
|
|
|
|
* data is in the form:
|
|
|
|
|
* IPv6 address: [ffff:ffff::ffff:ffff]:port:expire
|
|
|
|
|
* IPv4 address: a.b.c.d:port:expire
|
|
|
|
|
*/
|
|
|
|
|
c = data;
|
|
|
|
|
if (*c == '[') {
|
|
|
|
|
/* Need to skip over the IPv6 address. */
|
|
|
|
|
c = strchr(c, ']');
|
|
|
|
|
}
|
|
|
|
|
if (c) {
|
|
|
|
|
c = strchr(c, ':');
|
|
|
|
|
}
|
|
|
|
|
if (c) {
|
|
|
|
|
*c = '\0';
|
|
|
|
|
c++;
|
|
|
|
|
if (sscanf(c, "%5d:%30d", &port, &expire) == 2) {
|
|
|
|
|
/* Got it! */
|
|
|
|
|
inet_aton(data, &peer->addr.sin_addr);
|
|
|
|
|
peer->addr.sin_family = AF_INET;
|
|
|
|
|
peer->addr.sin_port = htons(port);
|
|
|
|
|
struct ast_sockaddr *addrs;
|
|
|
|
|
|
|
|
|
|
if (ast_sockaddr_resolve(&addrs, data, PARSE_PORT_FORBID, AF_UNSPEC) > 0){
|
|
|
|
|
ast_sockaddr_copy(&peer->addr, &addrs[0]);
|
|
|
|
|
ast_free(addrs);
|
|
|
|
|
}
|
|
|
|
|
ast_sockaddr_set_port(&peer->addr, port);
|
|
|
|
|
peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -4565,11 +4606,10 @@ static void populate_addr(struct dundi_peer *peer, dundi_eid *eid)
|
|
|
|
|
static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode)
|
|
|
|
|
{
|
|
|
|
|
struct dundi_peer *peer;
|
|
|
|
|
struct ast_hostent he;
|
|
|
|
|
struct hostent *hp;
|
|
|
|
|
dundi_eid testeid;
|
|
|
|
|
int needregister=0;
|
|
|
|
|
char eid_str[20];
|
|
|
|
|
int port = 0;
|
|
|
|
|
|
|
|
|
|
AST_LIST_LOCK(&peers);
|
|
|
|
|
AST_LIST_TRAVERSE(&peers, peer, list) {
|
|
|
|
@ -4586,8 +4626,6 @@ static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode
|
|
|
|
|
peer->registerid = -1;
|
|
|
|
|
peer->registerexpire = -1;
|
|
|
|
|
peer->qualifyid = -1;
|
|
|
|
|
peer->addr.sin_family = AF_INET;
|
|
|
|
|
peer->addr.sin_port = htons(DUNDI_PORT);
|
|
|
|
|
populate_addr(peer, eid);
|
|
|
|
|
AST_LIST_INSERT_HEAD(&peers, peer, list);
|
|
|
|
|
}
|
|
|
|
@ -4603,15 +4641,17 @@ static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode
|
|
|
|
|
} else if (!strcasecmp(v->name, "outkey")) {
|
|
|
|
|
ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey));
|
|
|
|
|
} else if (!strcasecmp(v->name, "port")) {
|
|
|
|
|
peer->addr.sin_port = htons(atoi(v->value));
|
|
|
|
|
port = atoi(v->value);
|
|
|
|
|
} else if (!strcasecmp(v->name, "host")) {
|
|
|
|
|
if (!strcasecmp(v->value, "dynamic")) {
|
|
|
|
|
peer->dynamic = 1;
|
|
|
|
|
} else {
|
|
|
|
|
hp = ast_gethostbyname(v->value, &he);
|
|
|
|
|
if (hp) {
|
|
|
|
|
memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr));
|
|
|
|
|
struct ast_sockaddr *addrs;
|
|
|
|
|
|
|
|
|
|
if (ast_sockaddr_resolve(&addrs, v->value, PARSE_PORT_FORBID, AF_UNSPEC) > 0) {
|
|
|
|
|
ast_sockaddr_copy(&peer->addr, &addrs[0]);
|
|
|
|
|
peer->dynamic = 0;
|
|
|
|
|
ast_free(addrs);
|
|
|
|
|
} else {
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);
|
|
|
|
|
peer->dead = 1;
|
|
|
|
@ -4682,6 +4722,11 @@ static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ast_sockaddr_isnull(&peer->addr)) {
|
|
|
|
|
ast_sockaddr_set_port(&peer->addr, (0 < port) ? port : DUNDI_PORT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(*globalpcmode) |= peer->pcmodel;
|
|
|
|
|
if (!peer->model && !peer->pcmodel) {
|
|
|
|
|
ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n",
|
|
|
|
@ -4831,20 +4876,54 @@ static struct ast_switch dundi_switch = {
|
|
|
|
|
.matchmore = dundi_matchmore,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int set_config(char *config_file, struct sockaddr_in* sin, int reload)
|
|
|
|
|
static int get_ipaddress(char *ip, size_t size, const char *str, int family)
|
|
|
|
|
{
|
|
|
|
|
struct ast_sockaddr *addrs;
|
|
|
|
|
|
|
|
|
|
if (!ast_sockaddr_resolve(&addrs, str, 0, family)) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast_copy_string(ip, ast_sockaddr_stringify_host(&addrs[0]), size);
|
|
|
|
|
ast_free(addrs);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void set_host_ipaddr(struct ast_sockaddr *sin)
|
|
|
|
|
{
|
|
|
|
|
char hn[MAXHOSTNAMELEN];
|
|
|
|
|
struct addrinfo hints;
|
|
|
|
|
int family;
|
|
|
|
|
|
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
|
|
|
|
|
|
if (ast_sockaddr_is_ipv6(sin)) {
|
|
|
|
|
family = AF_INET6;
|
|
|
|
|
} else {
|
|
|
|
|
family = AF_INET;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (gethostname(hn, sizeof(hn) - 1) < 0) {
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to get host name!\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get_ipaddress(ipaddr, sizeof(ipaddr), hn, family);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int set_config(char *config_file, struct ast_sockaddr *sin, int reload)
|
|
|
|
|
{
|
|
|
|
|
struct ast_config *cfg;
|
|
|
|
|
struct ast_variable *v;
|
|
|
|
|
char *cat;
|
|
|
|
|
int x;
|
|
|
|
|
struct ast_flags config_flags = { 0 };
|
|
|
|
|
char hn[MAXHOSTNAMELEN] = "";
|
|
|
|
|
struct ast_hostent he;
|
|
|
|
|
struct hostent *hp;
|
|
|
|
|
struct sockaddr_in sin2;
|
|
|
|
|
static int last_port = 0;
|
|
|
|
|
int port = 0;
|
|
|
|
|
int globalpcmodel = 0;
|
|
|
|
|
dundi_eid testeid;
|
|
|
|
|
char bind_addr[80];
|
|
|
|
|
|
|
|
|
|
if (!(cfg = ast_config_load(config_file, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
|
|
|
|
|
ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
|
|
|
|
@ -4855,16 +4934,6 @@ static int set_config(char *config_file, struct sockaddr_in* sin, int reload)
|
|
|
|
|
dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME;
|
|
|
|
|
any_peer = NULL;
|
|
|
|
|
|
|
|
|
|
ipaddr[0] = '\0';
|
|
|
|
|
if (!gethostname(hn, sizeof(hn)-1)) {
|
|
|
|
|
hp = ast_gethostbyname(hn, &he);
|
|
|
|
|
if (hp) {
|
|
|
|
|
memcpy(&sin2.sin_addr, hp->h_addr, sizeof(sin2.sin_addr));
|
|
|
|
|
ast_copy_string(ipaddr, ast_inet_ntoa(sin2.sin_addr), sizeof(ipaddr));
|
|
|
|
|
} else
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn);
|
|
|
|
|
} else
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to get host name!\n");
|
|
|
|
|
AST_LIST_LOCK(&peers);
|
|
|
|
|
|
|
|
|
|
if (ast_eid_is_empty(&ast_eid_default)) {
|
|
|
|
@ -4877,19 +4946,13 @@ static int set_config(char *config_file, struct sockaddr_in* sin, int reload)
|
|
|
|
|
v = ast_variable_browse(cfg, "general");
|
|
|
|
|
while(v) {
|
|
|
|
|
if (!strcasecmp(v->name, "port")){
|
|
|
|
|
sin->sin_port = htons(atoi(v->value));
|
|
|
|
|
if(last_port==0){
|
|
|
|
|
last_port=sin->sin_port;
|
|
|
|
|
} else if(sin->sin_port != last_port)
|
|
|
|
|
ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n");
|
|
|
|
|
port = atoi(v->value);
|
|
|
|
|
} else if (!strcasecmp(v->name, "bindaddr")) {
|
|
|
|
|
struct hostent *hep;
|
|
|
|
|
struct ast_hostent hent;
|
|
|
|
|
hep = ast_gethostbyname(v->value, &hent);
|
|
|
|
|
if (hep) {
|
|
|
|
|
memcpy(&sin->sin_addr, hep->h_addr, sizeof(sin->sin_addr));
|
|
|
|
|
} else
|
|
|
|
|
ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
|
|
|
|
|
if (get_ipaddress(bind_addr, sizeof(bind_addr), v->value, AF_UNSPEC) == 0) {
|
|
|
|
|
if (!ast_sockaddr_parse(sin, bind_addr, 0)) {
|
|
|
|
|
ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (!strcasecmp(v->name, "authdebug")) {
|
|
|
|
|
authdebug = ast_true(v->value);
|
|
|
|
|
} else if (!strcasecmp(v->name, "ttl")) {
|
|
|
|
@ -4944,6 +5007,26 @@ static int set_config(char *config_file, struct sockaddr_in* sin, int reload)
|
|
|
|
|
}
|
|
|
|
|
v = v->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (port == 0) {
|
|
|
|
|
port = DUNDI_PORT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ast_sockaddr_isnull(sin)) {
|
|
|
|
|
sprintf(bind_addr, "0.0.0.0:%d", port);
|
|
|
|
|
ast_sockaddr_parse(sin, bind_addr, 0);
|
|
|
|
|
} else {
|
|
|
|
|
ast_sockaddr_set_port(sin, port);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (last_port == 0) {
|
|
|
|
|
last_port = port;
|
|
|
|
|
} else if (last_port != port) {
|
|
|
|
|
ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set_host_ipaddr(sin);
|
|
|
|
|
|
|
|
|
|
AST_LIST_UNLOCK(&peers);
|
|
|
|
|
|
|
|
|
|
mark_mappings();
|
|
|
|
@ -5030,7 +5113,9 @@ static int unload_module(void)
|
|
|
|
|
|
|
|
|
|
static int reload(void)
|
|
|
|
|
{
|
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
|
struct ast_sockaddr sin;
|
|
|
|
|
|
|
|
|
|
ast_sockaddr_setnull(&sin);
|
|
|
|
|
|
|
|
|
|
if (set_config("dundi.conf", &sin, 1))
|
|
|
|
|
return AST_MODULE_LOAD_FAILURE;
|
|
|
|
@ -5040,15 +5125,11 @@ static int reload(void)
|
|
|
|
|
|
|
|
|
|
static int load_module(void)
|
|
|
|
|
{
|
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
|
struct ast_sockaddr sin;
|
|
|
|
|
|
|
|
|
|
dundi_set_output(dundi_debug_output);
|
|
|
|
|
dundi_set_error(dundi_error_output);
|
|
|
|
|
|
|
|
|
|
sin.sin_family = AF_INET;
|
|
|
|
|
sin.sin_port = htons(DUNDI_PORT);
|
|
|
|
|
sin.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
|
|
|
|
|
|
/* Make a UDP socket */
|
|
|
|
|
io = io_context_create();
|
|
|
|
|
sched = ast_sched_context_create();
|
|
|
|
@ -5057,19 +5138,25 @@ static int load_module(void)
|
|
|
|
|
goto declined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast_sockaddr_setnull(&sin);
|
|
|
|
|
|
|
|
|
|
if (set_config("dundi.conf", &sin, 0)) {
|
|
|
|
|
goto declined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
|
|
|
|
if (ast_sockaddr_is_ipv6(&sin)) {
|
|
|
|
|
netsocket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
|
|
|
|
|
} else {
|
|
|
|
|
netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (netsocket < 0) {
|
|
|
|
|
ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
|
|
|
|
|
goto declined;
|
|
|
|
|
}
|
|
|
|
|
if (bind(netsocket, (struct sockaddr *) &sin, sizeof(sin))) {
|
|
|
|
|
ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n",
|
|
|
|
|
ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), strerror(errno));
|
|
|
|
|
if (ast_bind(netsocket, &sin)) {
|
|
|
|
|
ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",
|
|
|
|
|
ast_sockaddr_stringify(&sin), strerror(errno));
|
|
|
|
|
goto declined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -5087,7 +5174,7 @@ static int load_module(void)
|
|
|
|
|
ast_custom_function_register(&dundi_query_function);
|
|
|
|
|
ast_custom_function_register(&dundi_result_function);
|
|
|
|
|
|
|
|
|
|
ast_verb(2, "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
|
|
|
|
|
ast_verb(2, "DUNDi Ready and Listening on %s\n", ast_sockaddr_stringify(&sin));
|
|
|
|
|
|
|
|
|
|
return AST_MODULE_LOAD_SUCCESS;
|
|
|
|
|
|
|
|
|
|