static int determine_firstline_parts(struct sip_request *req);
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 void set_insecure_flags(struct ast_flags *flags, const char *value, int lineno);
static int find_sip_method(const char *msg);
static unsigned int parse_sip_options(struct sip_pvt *pvt, const char *supported);
static void parse_request(struct sip_request *req);
*/
static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_in *sin)
{
- struct sip_peer *peer;
- struct ast_variable *var = NULL;
+ struct sip_peer *peer=NULL;
+ struct ast_variable *var;
+ struct ast_config *peerlist = NULL;
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 */
if (newpeername)
var = ast_load_realtime("sippeers", "name", newpeername, NULL);
- else if (sin) { /* Then check on IP address for dynamic peers */
- ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr));
- var = ast_load_realtime("sippeers", "host", ipaddr, NULL); /* First check for fixed IP hosts */
+ else if (sin) { /* Then check on IP address */
+ iabuf = ast_inet_ntoa(sin->sin_addr);
+ 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)
- 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(peerlist)
+ ast_config_destroy(peerlist);
return NULL;
for (tmp = var; tmp; tmp = tmp->next) {
}
if (!newpeername) { /* Did not find peer in realtime */
- ast_log(LOG_WARNING, "Cannot Determine peer name ip=%s\n", ipaddr);
- ast_variables_destroy(var);
+ ast_log(LOG_WARNING, "Cannot Determine peer name ip=%s\n", iabuf);
+ if(peerlist)
+ ast_config_destroy(peerlist);
+ else
+ ast_variables_destroy(var);
return NULL;
}
/* Peer found in realtime, now build it in memory */
peer = build_peer(newpeername, var, NULL, !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS));
if (!peer) {
- ast_variables_destroy(var);
+ if(peerlist)
+ ast_config_destroy(peerlist);
+ else
+ ast_variables_destroy(var);
return NULL;
}
} else {
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 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
\param flags array of two struct ast_flags
} else if (!strcasecmp(v->name, "canreinvite")) {
ast_set_flag(&mask[0], SIP_REINVITE);
ast_clear_flag(&flags[0], SIP_REINVITE);
- if (ast_true(v->value)) {
- 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);
- }
- }
- }
+ set_insecure_flags(flags, v->value, v->lineno);
} else if (!strcasecmp(v->name, "insecure")) {
ast_set_flag(&mask[0], SIP_INSECURE_PORT | SIP_INSECURE_INVITE);
ast_clear_flag(&flags[0], SIP_INSECURE_PORT | SIP_INSECURE_INVITE);