Changed the behavior of sip's realtime_peer function to match the corresponding way of matching for non-realtime peers.

Now matches are made on both the IP address and port number, or if the insecure setting is set to "port" then just match on the
IP address.

In order to accomplish this, I also added a new API call, ast_category_root, which returns the first variable of an ast_category struct



git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@78103 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Michelson
2007-08-03 20:25:22 +00:00
parent 76f4f0218c
commit 05ba4d90d4
3 changed files with 109 additions and 31 deletions

View File

@@ -1443,6 +1443,7 @@ static void append_date(struct sip_request *req); /* Append date to SIP packet *
static int determine_firstline_parts(struct sip_request *req); static int determine_firstline_parts(struct sip_request *req);
static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype); static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype);
static const char *gettag(const struct sip_request *req, const char *header, char *tagbuf, int tagbufsize); static const char *gettag(const struct sip_request *req, const char *header, char *tagbuf, int tagbufsize);
static void set_insecure_flags(struct ast_flags *flags, const char *value, int lineno);
static int find_sip_method(const char *msg); static int find_sip_method(const char *msg);
static unsigned int parse_sip_options(struct sip_pvt *pvt, const char *supported); static unsigned int parse_sip_options(struct sip_pvt *pvt, const char *supported);
static void parse_request(struct sip_request *req); static void parse_request(struct sip_request *req);
@@ -2454,22 +2455,64 @@ static void update_peer(struct sip_peer *p, int expiry)
*/ */
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)
{ {
struct sip_peer *peer; struct sip_peer *peer=NULL;
struct ast_variable *var = NULL; struct ast_variable *var;
struct ast_config *peerlist = NULL;
struct ast_variable *tmp; struct ast_variable *tmp;
char ipaddr[INET_ADDRSTRLEN]; struct ast_flags flags = {0};
const char *iabuf;
char portstring[6]; /*up to five digits plus null terminator*/
const char *insecure;
char *cat = NULL;
unsigned short portnum;
/* First check on peer name */ /* First check on peer name */
if (newpeername) if (newpeername)
var = ast_load_realtime("sippeers", "name", newpeername, NULL); var = ast_load_realtime("sippeers", "name", newpeername, NULL);
else if (sin) { /* Then check on IP address for dynamic peers */ else if (sin) { /* Then check on IP address */
ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr)); iabuf = ast_inet_ntoa(sin->sin_addr);
var = ast_load_realtime("sippeers", "host", ipaddr, NULL); /* First check for fixed IP hosts */ portnum = ntohs(sin->sin_port);
sprintf(portstring, "%d", portnum);
var = ast_load_realtime("sippeers", "host", iabuf, "port", portstring, NULL); /* First check for fixed IP hosts */
if (!var) if (!var)
var = ast_load_realtime("sippeers", "ipaddr", ipaddr, NULL); /* Then check for registred hosts */ var = ast_load_realtime("sippeers", "ipaddr", iabuf, "port", portstring, NULL); /* Then check for registered hosts */
} if (!var) {
peerlist = ast_load_realtime_multientry("sippeers", "host", iabuf, NULL); /*No exact match, see if port is insecure, try host match first*/
if(peerlist){
while((cat = ast_category_browse(peerlist, cat)))
{
insecure = ast_variable_retrieve(peerlist, cat, "insecure");
set_insecure_flags(&flags, insecure, -1);
if(ast_test_flag(&flags, SIP_INSECURE_PORT)) {
var = ast_category_root(peerlist, cat);
break;
}
}
}
if(!var) {
ast_config_destroy(peerlist);
peerlist = NULL; /*for safety's sake*/
cat = NULL;
peerlist = ast_load_realtime_multientry("sippeers", "ipaddr", iabuf, NULL); /*No exact match, see if port is insecure, now try ip address match*/
if(peerlist) {
while((cat = ast_category_browse(peerlist, cat)))
{
insecure = ast_variable_retrieve(peerlist, cat, "insecure");
set_insecure_flags(&flags, insecure, -1);
if(ast_test_flag(&flags, SIP_INSECURE_PORT)) {
var = ast_category_root(peerlist, cat);
break;
}
}
}
}
}
} else
return NULL;
if (!var) if (!var)
if(peerlist)
ast_config_destroy(peerlist);
return NULL; return NULL;
for (tmp = var; tmp; tmp = tmp->next) { for (tmp = var; tmp; tmp = tmp->next) {
@@ -2484,15 +2527,21 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
} }
if (!newpeername) { /* Did not find peer in realtime */ if (!newpeername) { /* Did not find peer in realtime */
ast_log(LOG_WARNING, "Cannot Determine peer name ip=%s\n", ipaddr); ast_log(LOG_WARNING, "Cannot Determine peer name ip=%s\n", iabuf);
ast_variables_destroy(var); if(peerlist)
ast_config_destroy(peerlist);
else
ast_variables_destroy(var);
return NULL; return NULL;
} }
/* Peer found in realtime, now build it in memory */ /* Peer found in realtime, now build it in memory */
peer = build_peer(newpeername, var, NULL, !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)); peer = build_peer(newpeername, var, NULL, !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS));
if (!peer) { if (!peer) {
ast_variables_destroy(var); if(peerlist)
ast_config_destroy(peerlist);
else
ast_variables_destroy(var);
return NULL; return NULL;
} }
@@ -2509,8 +2558,10 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
} else { } else {
ast_set_flag(&peer->flags[0], SIP_REALTIME); ast_set_flag(&peer->flags[0], SIP_REALTIME);
} }
ast_variables_destroy(var); if(peerlist)
ast_config_destroy(peerlist);
else
ast_variables_destroy(var);
return peer; return peer;
} }
@@ -15621,6 +15672,34 @@ static struct ast_channel *sip_request_call(const char *type, int format, void *
return tmpc; return tmpc;
} }
/*!
* \brief Parse the "insecure" setting from sip.conf or from realtime.
* \param flags a pointer to an ast_flags structure
* \param value the value of the SIP insecure setting
* \param lineno linenumber in sip.conf or -1 for realtime
*/
static void set_insecure_flags(struct ast_flags *flags, const char *value, int lineno)
{
if (!strcasecmp(value, "very"))
ast_set_flag(flags, SIP_INSECURE_PORT | SIP_INSECURE_INVITE);
else if (ast_true(value))
ast_set_flag(flags, SIP_INSECURE_PORT);
else if (!ast_false(value)) {
char buf[64];
char *word, *next;
ast_copy_string(buf, value, sizeof(buf));
next = buf;
while ((word = strsep(&next, ","))) {
if (!strcasecmp(word, "port"))
ast_set_flag(flags, SIP_INSECURE_PORT);
else if (!strcasecmp(word, "invite"))
ast_set_flag(flags, SIP_INSECURE_INVITE);
else
ast_log(LOG_WARNING, "Unknown insecure mode '%s' on line %d\n", value, lineno);
}
}
}
/*! /*!
\brief Handle flag-type options common to configuration of devices - users and peers \brief Handle flag-type options common to configuration of devices - users and peers
\param flags array of two struct ast_flags \param flags array of two struct ast_flags
@@ -15675,24 +15754,7 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
} else if (!strcasecmp(v->name, "canreinvite")) { } else if (!strcasecmp(v->name, "canreinvite")) {
ast_set_flag(&mask[0], SIP_REINVITE); ast_set_flag(&mask[0], SIP_REINVITE);
ast_clear_flag(&flags[0], SIP_REINVITE); ast_clear_flag(&flags[0], SIP_REINVITE);
if (ast_true(v->value)) { set_insecure_flags(flags, v->value, v->lineno);
ast_set_flag(&flags[0], SIP_CAN_REINVITE | SIP_CAN_REINVITE_NAT);
} else if (!ast_false(v->value)) {
char buf[64];
char *word, *next = buf;
ast_copy_string(buf, v->value, sizeof(buf));
while ((word = strsep(&next, ","))) {
if (!strcasecmp(word, "update")) {
ast_set_flag(&flags[0], SIP_REINVITE_UPDATE | SIP_CAN_REINVITE);
} else if (!strcasecmp(word, "nonat")) {
ast_set_flag(&flags[0], SIP_CAN_REINVITE);
ast_clear_flag(&flags[0], SIP_CAN_REINVITE_NAT);
} else {
ast_log(LOG_WARNING, "Unknown canreinvite mode '%s' on line %d\n", v->value, v->lineno);
}
}
}
} else if (!strcasecmp(v->name, "insecure")) { } else if (!strcasecmp(v->name, "insecure")) {
ast_set_flag(&mask[0], SIP_INSECURE_PORT | SIP_INSECURE_INVITE); ast_set_flag(&mask[0], SIP_INSECURE_PORT | SIP_INSECURE_INVITE);
ast_clear_flag(&flags[0], SIP_INSECURE_PORT | SIP_INSECURE_INVITE); ast_clear_flag(&flags[0], SIP_INSECURE_PORT | SIP_INSECURE_INVITE);

View File

@@ -75,6 +75,14 @@ struct ast_config *ast_config_load_with_comments(const char *filename);
*/ */
void ast_config_destroy(struct ast_config *config); void ast_config_destroy(struct ast_config *config);
/*! \brief returns the root ast_variable of a config
* \param config pointer to an ast_config data structure
* \param cat name of the category for which you want the root
*
* Returns the category specified
*/
struct ast_variable *ast_category_root(struct ast_config *config, char *cat);
/*! \brief Goes through categories /*! \brief Goes through categories
* \param config Which config structure you wish to "browse" * \param config Which config structure you wish to "browse"
* \param prev A pointer to a previous category. * \param prev A pointer to a previous category.

View File

@@ -353,6 +353,14 @@ static struct ast_category *next_available_category(struct ast_category *cat)
return cat; return cat;
} }
struct ast_variable *ast_category_root(struct ast_config *config, char *cat)
{
struct ast_category *category = ast_category_get(config, cat);
if (category)
return category->root;
return NULL;
}
char *ast_category_browse(struct ast_config *config, const char *prev) char *ast_category_browse(struct ast_config *config, const char *prev)
{ {
struct ast_category *cat = NULL; struct ast_category *cat = NULL;