mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
341 lines
8.8 KiB
341 lines
8.8 KiB
/*
|
|
* Copyright (C) 2005 iptelorg GmbH
|
|
*
|
|
* This file is part of ser, a free SIP server.
|
|
*
|
|
* ser is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version
|
|
*
|
|
* For a license to use the ser software under conditions
|
|
* other than those described here, or to purchase support for this
|
|
* software, please contact iptel.org by e-mail at the following addresses:
|
|
* info@iptel.org
|
|
*
|
|
* ser is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include <xcap/parse_common_rules.h>
|
|
#include <xcap/xcap_result_codes.h>
|
|
|
|
#include <cds/dstring.h>
|
|
#include <cds/memory.h>
|
|
#include <cds/logger.h>
|
|
#include <cds/list.h>
|
|
#include <string.h>
|
|
|
|
#include <xcap/xml_utils.h>
|
|
|
|
char *common_policy_ns = NULL;
|
|
|
|
static int read_sphere(xmlNode *n, cp_sphere_t **dst)
|
|
{
|
|
*dst = (cp_sphere_t*)cds_malloc(sizeof(cp_sphere_t));
|
|
if (!(*dst)) return RES_MEMORY_ERR;
|
|
memset(*dst, 0, sizeof(**dst));
|
|
(*dst)->next = NULL;
|
|
|
|
str_dup_zt(&(*dst)->value, get_node_value(n));
|
|
return RES_OK;
|
|
}
|
|
|
|
static int read_validity(xmlNode *n, cp_validity_t **dst)
|
|
{
|
|
const char *from, *to;
|
|
*dst = (cp_validity_t*)cds_malloc(sizeof(cp_validity_t));
|
|
if (!(*dst)) return RES_MEMORY_ERR;
|
|
memset(*dst, 0, sizeof(**dst));
|
|
|
|
from = get_node_value(find_node(n, "from", common_policy_ns));
|
|
to = get_node_value(find_node(n, "to", common_policy_ns));
|
|
|
|
(*dst)->from = xmltime2time(from);
|
|
(*dst)->to = xmltime2time(to);
|
|
return RES_OK;
|
|
}
|
|
|
|
static int read_id(xmlNode *n, cp_id_t **dst)
|
|
{
|
|
*dst = (cp_id_t*)cds_malloc(sizeof(cp_id_t));
|
|
if (!(*dst)) return RES_MEMORY_ERR;
|
|
memset(*dst, 0, sizeof(**dst));
|
|
(*dst)->next = NULL;
|
|
|
|
get_str_attr(n, "entity", &(*dst)->entity);
|
|
if ((*dst)->entity.len == 0) {
|
|
/* hack - eyeBeams format differs from draft ! */
|
|
str_dup_zt(&(*dst)->entity, get_node_value(n));
|
|
}
|
|
|
|
return RES_OK;
|
|
}
|
|
|
|
static int read_domain(xmlNode *n, cp_domain_t **dst)
|
|
{
|
|
*dst = (cp_domain_t*)cds_malloc(sizeof(cp_domain_t));
|
|
if (!(*dst)) return RES_MEMORY_ERR;
|
|
memset(*dst, 0, sizeof(**dst));
|
|
(*dst)->next = NULL;
|
|
|
|
get_str_attr(n, "domain", &(*dst)->domain);
|
|
return RES_OK;
|
|
}
|
|
|
|
static int read_except(xmlNode *n, cp_except_t **dst)
|
|
{
|
|
*dst = (cp_except_t*)cds_malloc(sizeof(cp_except_t));
|
|
if (!(*dst)) return RES_MEMORY_ERR;
|
|
memset(*dst, 0, sizeof(**dst));
|
|
(*dst)->next = NULL;
|
|
|
|
get_str_attr(n, "entity", &(*dst)->entity);
|
|
return RES_OK;
|
|
}
|
|
|
|
static int read_except_domain(xmlNode *n, cp_except_domain_t **dst)
|
|
{
|
|
*dst = (cp_except_domain_t*)cds_malloc(sizeof(cp_except_domain_t));
|
|
if (!*dst) return RES_MEMORY_ERR;
|
|
memset(*dst, 0, sizeof(**dst));
|
|
(*dst)->next = NULL;
|
|
|
|
get_str_attr(n, "domain", &(*dst)->domain);
|
|
return RES_OK;
|
|
}
|
|
|
|
static int read_any_identity(xmlNode *an, cp_any_identity_t **dst)
|
|
{
|
|
cp_domain_t *domain, *last_domain = NULL;
|
|
cp_except_domain_t *except, *last_except = NULL;
|
|
xmlNode *n;
|
|
int res = RES_OK;
|
|
|
|
*dst = (cp_any_identity_t*)cds_malloc(sizeof(cp_any_identity_t));
|
|
if (!*dst) return RES_MEMORY_ERR;
|
|
memset(*dst, 0, sizeof(**dst));
|
|
|
|
n = an->children;
|
|
while (n) {
|
|
if (n->type == XML_ELEMENT_NODE) {
|
|
if (cmp_node(n, "domain", common_policy_ns) >= 0) {
|
|
res = read_domain(n, &domain);
|
|
if (res != 0) break;
|
|
LINKED_LIST_ADD((*dst)->domains, last_domain, domain);
|
|
}
|
|
else if (cmp_node(n, "except-domain", common_policy_ns) >= 0) {
|
|
res = read_except_domain(n, &except);
|
|
if (res != 0) break;
|
|
LINKED_LIST_ADD((*dst)->except_domains, last_except, except);
|
|
}
|
|
}
|
|
|
|
n = n->next;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static int read_identity(xmlNode *idn, cp_identity_t **dst)
|
|
{
|
|
cp_id_t *id, *last_id = NULL;
|
|
cp_domain_t *domain, *last_domain = NULL;
|
|
cp_except_t *except, *last_except = NULL;
|
|
xmlNode *n;
|
|
int res = RES_OK;
|
|
|
|
*dst = (cp_identity_t*)cds_malloc(sizeof(cp_identity_t));
|
|
if (!*dst) return RES_MEMORY_ERR;
|
|
memset(*dst, 0, sizeof(**dst));
|
|
|
|
n = idn->children;
|
|
while (n) {
|
|
if (n->type == XML_ELEMENT_NODE) {
|
|
if (cmp_node(n, "id", common_policy_ns) >= 0) {
|
|
res = read_id(n, &id);
|
|
if (res != 0) break;
|
|
LINKED_LIST_ADD((*dst)->ids, last_id, id);
|
|
}
|
|
else if (cmp_node(n, "domain", common_policy_ns) >= 0) {
|
|
res = read_domain(n, &domain);
|
|
if (res != 0) break;
|
|
LINKED_LIST_ADD((*dst)->domains, last_domain, domain);
|
|
}
|
|
else if (cmp_node(n, "except", common_policy_ns) >= 0) {
|
|
res = read_except(n, &except);
|
|
if (res != 0) break;
|
|
LINKED_LIST_ADD((*dst)->excepts, last_except, except);
|
|
}
|
|
else if (cmp_node(n, "any-identity", common_policy_ns) >= 0) {
|
|
res = read_any_identity(n, &(*dst)->any_identity);
|
|
if (res != 0) break;
|
|
}
|
|
}
|
|
|
|
n = n->next;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int read_conditions(xmlNode *cn, cp_conditions_t **dst)
|
|
{
|
|
xmlNode *n;
|
|
int res = RES_OK;
|
|
cp_sphere_t *sphere, * last_sphere = NULL;
|
|
if ((!cn) || (!dst)) return RES_INTERNAL_ERR;
|
|
|
|
*dst = (cp_conditions_t*)cds_malloc(sizeof(cp_conditions_t));
|
|
if (!(*dst)) return RES_MEMORY_ERR;
|
|
memset(*dst, 0, sizeof(cp_conditions_t));
|
|
|
|
n = cn->children;
|
|
while (n) {
|
|
if (n->type == XML_ELEMENT_NODE) {
|
|
if (cmp_node(n, "validity", common_policy_ns) >= 0) {
|
|
/* FIXME: free existing validity */
|
|
res = read_validity(n, &(*dst)->validity);
|
|
if (res != 0) break;
|
|
}
|
|
else {
|
|
if (cmp_node(n, "identity", common_policy_ns) >= 0) {
|
|
/* FIXME: free existing identity */
|
|
res = read_identity(n, &(*dst)->identity);
|
|
if (res != 0) break;
|
|
}
|
|
else {
|
|
if (cmp_node(n, "sphere", common_policy_ns) >= 0) {
|
|
res = read_sphere(n, &sphere);
|
|
if (res != 0) break;
|
|
LINKED_LIST_ADD((*dst)->spheres, last_sphere, sphere);
|
|
}
|
|
/* else process other elements ? */
|
|
}
|
|
|
|
}
|
|
}
|
|
n = n->next;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int read_transformations(xmlNode *tn, cp_transformations_t **dst)
|
|
{
|
|
int res = RES_OK;
|
|
if ((!tn) || (!dst)) return RES_INTERNAL_ERR;
|
|
|
|
*dst = (cp_transformations_t*)cds_malloc(sizeof(cp_transformations_t));
|
|
if (!*dst) return RES_MEMORY_ERR;
|
|
memset(*dst, 0, sizeof(cp_transformations_t));
|
|
|
|
DEBUG_LOG("transformations for pres_rules not used\n");
|
|
|
|
return res;
|
|
}
|
|
|
|
static int read_rule(xmlNode *rn, cp_rule_t **dst,
|
|
cp_read_actions_func read_actions,
|
|
cp_free_actions_func free_actions)
|
|
{
|
|
xmlNode *n;
|
|
int res = RES_OK;
|
|
if ((!rn) || (!dst)) return RES_INTERNAL_ERR;
|
|
|
|
*dst = (cp_rule_t*)cds_malloc(sizeof(cp_rule_t));
|
|
if (!*dst) return RES_MEMORY_ERR;
|
|
memset(*dst, 0, sizeof(cp_rule_t));
|
|
|
|
get_str_attr(rn, "id", &(*dst)->id);
|
|
|
|
n = find_node(rn, "actions", common_policy_ns);
|
|
if (n && (res == 0) && read_actions) res = read_actions(n, &(*dst)->actions);
|
|
|
|
n = find_node(rn, "conditions", common_policy_ns);
|
|
if (n && (res == 0)) res = read_conditions(n, &(*dst)->conditions);
|
|
|
|
n = find_node(rn, "transformations", common_policy_ns);
|
|
if (n && (res == 0)) res = read_transformations(n, &(*dst)->transformations);
|
|
|
|
if (res != 0) {
|
|
free_cp_rule(*dst, free_actions);
|
|
*dst = NULL;
|
|
return res;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int read_common_rules(xmlNode *root, cp_ruleset_t **dst,
|
|
cp_read_actions_func read_actions, cp_free_actions_func free_actions)
|
|
{
|
|
cp_ruleset_t *rs = NULL;
|
|
cp_rule_t *r, *last = NULL;
|
|
xmlNode *n;
|
|
int res = RES_OK;
|
|
|
|
if (!dst) return RES_INTERNAL_ERR;
|
|
else *dst = NULL;
|
|
if (!root) return RES_INTERNAL_ERR;
|
|
|
|
if (cmp_node(root, "ruleset", common_policy_ns) < 0) {
|
|
ERROR_LOG("document is not a ruleset \n");
|
|
return RES_INTERNAL_ERR;
|
|
}
|
|
|
|
rs = (cp_ruleset_t*)cds_malloc(sizeof(cp_ruleset_t));
|
|
if (!rs) return RES_MEMORY_ERR;
|
|
*dst = rs;
|
|
memset(rs, 0, sizeof(*rs));
|
|
|
|
|
|
/* read rules in ruleset */
|
|
n = root->children;
|
|
while (n) {
|
|
if (n->type == XML_ELEMENT_NODE) {
|
|
if (cmp_node(n, "rule", common_policy_ns) >= 0) {
|
|
res = read_rule(n, &r, read_actions, free_actions);
|
|
if (res == 0) {
|
|
if (r) LINKED_LIST_ADD(rs->rules, last, r);
|
|
}
|
|
else break;
|
|
}
|
|
}
|
|
n = n->next;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
int parse_common_rules(const char *data, int dsize, cp_ruleset_t **dst,
|
|
cp_read_actions_func read_actions, cp_free_actions_func free_actions)
|
|
{
|
|
int res = 0;
|
|
xmlDocPtr doc; /* the resulting document tree */
|
|
|
|
if (dst) *dst = NULL;
|
|
doc = xmlReadMemory(data, dsize, NULL, NULL, xml_parser_flags);
|
|
if (doc == NULL) {
|
|
ERROR_LOG("can't parse document\n");
|
|
return RES_INTERNAL_ERR;
|
|
}
|
|
|
|
res = read_common_rules(xmlDocGetRootElement(doc), dst,
|
|
read_actions, free_actions);
|
|
if ((res != RES_OK) && (dst)) {
|
|
/* may be set => must be freed */
|
|
free_common_rules(*dst, free_actions);
|
|
*dst = NULL;
|
|
}
|
|
|
|
xmlFreeDoc(doc);
|
|
return res;
|
|
}
|
|
|