aboutsummaryrefslogtreecommitdiffstats
path: root/src/libosmocc/screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libosmocc/screen.c')
-rw-r--r--src/libosmocc/screen.c694
1 files changed, 0 insertions, 694 deletions
diff --git a/src/libosmocc/screen.c b/src/libosmocc/screen.c
deleted file mode 100644
index be12f08..0000000
--- a/src/libosmocc/screen.c
+++ /dev/null
@@ -1,694 +0,0 @@
-/* Endpoint and call process handling
- *
- * (C) 2019 by Andreas Eversberg <jolly@eversberg.eu>
- * All Rights Reserved
- *
- * This program 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 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include "../libtimer/timer.h"
-#include "../libselect/select.h"
-#include "../libdebug/debug.h"
-#include "endpoint.h"
-#include "message.h"
-
-#define SCREEN_QUESTIONMARK 1
-#define SCREEN_STAR 2
-#define SCREEN_AT 3
-
-void osmo_cc_help_screen(void)
-{
- printf("Screening options:\n\n");
-
- printf("screen-calling-in [attrs] <current caller ID> [attrs] <new caller ID>\n");
- printf("screen-called-in [attrs] <current dialed number> [attrs] <new dialed number>\n");
- printf("screen-calling-out [attrs] <current caller ID> [attrs] <new caller ID>\n");
- printf("screen-called-out [attrs] <current dialed number> [attrs] <new dialed number>\n\n");
-
- printf("These options allow to screen an incoming or outgoing caller ID or dialed\n");
- printf("number. If 'the current caller ID' or 'current dialed number' matches, it will\n");
- printf("be replaced by 'new caller ID' or 'new dialed number'. 'incoming' means from\n");
- printf(" the interface and 'outgoing' means towards the interface.\n\n");
-
- printf("Attributes prior 'current caller ID' or 'new dialed number' may be used to\n");
- printf("perform screening only if the attribute match. Attributes prior\n");
- printf("'new caller ID' or 'new dialed number' may be used to alter them. Attribute to\n");
- printf("define the type of number can be: 'unknown', 'international', 'national',\n");
- printf("'network', 'subscriber', 'abbreviated' Attribute to define the restriction of a\n");
- printf("caller ID: 'allowed', 'restricted'\n\n");
-
- printf("The current caller ID or dialed number may contain one or more '?', to allow\n");
- printf("any digit to match. The current caller ID or dialed number may contain a '*',\n");
- printf("to allow any suffix to match from now on. The new caller ID or dialed number\n");
- printf("may contain a '*', to append the suffix from the current caller ID or dialed\n");
- printf("number.\n\n");
-
- printf("When screening an incoming caller ID or dialed number, the '@' can be appended\n");
- printf("to the 'new caller ID', followed by a 'host:port', to route call to a special\n");
- printf("Osmo-CC endpoint. This way it is possible to do simple routing.\n\n");
-}
-
-char *osmo_cc_strtok_quotes(const char **text_p)
-{
- static char token[1024];
- const char *text = *text_p;
- int i, quote;
-
- /* skip spaces */
- while (*text) {
- if (*text > 32)
- break;
- text++;
- }
-
- /* if eol, return NULL */
- if (!(*text))
- return NULL;
-
- i = 0;
- quote = 0;
- while (*text) {
- /* escape allows all following characters */
- if (*text == '\\') {
- text++;
- if (*text)
- token[i++] = *text++;
- continue;
- }
- /* no quote, check for them or break on white space */
- if (quote == 0) {
- if (*text == '\'') {
- quote = 1;
- text++;
- continue;
- }
- if (*text == '\"') {
- quote = 2;
- text++;
- continue;
- }
- if (*text <= ' ')
- break;
- }
- /* single quote, check for unquote */
- if (quote == 1 && *text == '\'') {
- quote = 0;
- text++;
- continue;
- }
- /* double quote, check for unquote */
- if (quote == 2 && *text == '\"') {
- quote = 0;
- text++;
- continue;
- }
- /* copy character */
- token[i++] = *text++;
- }
- token[i] = '\0';
-
- *text_p = text;
- return token;
-}
-
-int osmo_cc_add_screen(osmo_cc_endpoint_t *ep, const char *text)
-{
- osmo_cc_screen_list_t **list_p = NULL, *list;
- const char *token;
- int no_present = 0, calling_in = 0, star_used, at_used;
- int i, j;
-
- star_used = 0;
- if (!strncasecmp(text, "screen-calling-in", 17)) {
- text += 17;
- list_p = &ep->screen_calling_in;
- no_present = 1;
- calling_in = 1;
- } else if (!strncasecmp(text, "screen-called-in", 16)) {
- text += 16;
- list_p = &ep->screen_called_in;
- calling_in = 1;
- } else if (!strncasecmp(text, "screen-calling-out", 18)) {
- text += 18;
- list_p = &ep->screen_calling_out;
- no_present = 1;
- } else if (!strncasecmp(text, "screen-called-out", 17)) {
- text += 17;
- list_p = &ep->screen_called_out;
- } else {
- LOGP(DCC, LOGL_ERROR, "Invalid screening definition \"%s\". It must start with 'screen-calling-in' or 'screen-called-in' or 'screen-calling-out' or 'screen-called-out'\n", text);
- return -EINVAL;
- }
-
- /* skip space behind screen list string */
- while (*text) {
- if (*text > 32)
- break;
- text++;
- }
-
- list = calloc(1, sizeof(*list));
- if (!list)
- return -ENOMEM;
-
-next_from:
- token = osmo_cc_strtok_quotes(&text);
- if (!token) {
- free(list);
- LOGP(DCC, LOGL_ERROR, "Missing 'from' string in screening definition \"%s\". If the string shall be empty, use double quotes. (\'\' or \"\")\n", text);
- return -EINVAL;
- }
- if (!strcasecmp(token, "unknown")) {
- list->has_from_type = 1;
- list->from_type = OSMO_CC_TYPE_UNKNOWN;
- goto next_from;
- } else
- if (!strcasecmp(token, "international")) {
- list->has_from_type = 1;
- list->from_type = OSMO_CC_TYPE_INTERNATIONAL;
- goto next_from;
- } else
- if (!strcasecmp(token, "national")) {
- list->has_from_type = 1;
- list->from_type = OSMO_CC_TYPE_NATIONAL;
- goto next_from;
- } else
- if (!strcasecmp(token, "network")) {
- list->has_from_type = 1;
- list->from_type = OSMO_CC_TYPE_NETWORK;
- goto next_from;
- } else
- if (!strcasecmp(token, "subscriber")) {
- list->has_from_type = 1;
- list->from_type = OSMO_CC_TYPE_SUBSCRIBER;
- goto next_from;
- } else
- if (!strcasecmp(token, "abbreviated")) {
- list->has_from_type = 1;
- list->from_type = OSMO_CC_TYPE_ABBREVIATED;
- goto next_from;
- } else
- if (!strcasecmp(token, "allowed")) {
- if (no_present) {
-no_present_error:
- free(list);
- LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
- LOGP(DCC, LOGL_ERROR, "Keyword '%s' not allowed in screen entry for called number\n", token);
- return -EINVAL;
- }
- list->has_from_present = 1;
- list->from_present = OSMO_CC_PRESENT_ALLOWED;
- goto next_from;
- } else
- if (!strcasecmp(token, "restricted")) {
- if (no_present)
- goto no_present_error;
- list->has_from_present = 1;
- list->from_present = OSMO_CC_PRESENT_RESTRICTED;
- goto next_from;
- } else {
- star_used = 0;
- for (i = j = 0; token[i] && j < (int)sizeof(list->from) - 1; i++, j++) {
- if (token[i] == '?')
- list->from[j] = SCREEN_QUESTIONMARK;
- else
- if (token[i] == '*') {
- if (star_used) {
- free(list);
- LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
- LOGP(DCC, LOGL_ERROR, "The '*' may be used only once.\n");
- return -EINVAL;
- }
- list->from[j] = SCREEN_STAR;
- star_used = 1;
- } else
- if (token[i] == '\\' && token[i + 1] != '\0')
- list->from[j] = token[++i];
- else
- list->from[j] = token[i];
- }
- list->from[j] = '\0';
- }
-
-next_to:
- token = osmo_cc_strtok_quotes(&text);
- if (!token) {
- free(list);
- LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
- LOGP(DCC, LOGL_ERROR, "Missing screening result. If the string shall be empty, use double quotes. (\'\' or \"\")\n");
- return -EINVAL;
- }
- if (!strcasecmp(token, "unknown")) {
- list->has_to_type = 1;
- list->to_type = OSMO_CC_TYPE_UNKNOWN;
- goto next_to;
- } else
- if (!strcasecmp(token, "international")) {
- list->has_to_type = 1;
- list->to_type = OSMO_CC_TYPE_INTERNATIONAL;
- goto next_to;
- } else
- if (!strcasecmp(token, "national")) {
- list->has_to_type = 1;
- list->to_type = OSMO_CC_TYPE_NATIONAL;
- goto next_to;
- } else
- if (!strcasecmp(token, "network")) {
- list->has_to_type = 1;
- list->to_type = OSMO_CC_TYPE_NETWORK;
- goto next_to;
- } else
- if (!strcasecmp(token, "subscriber")) {
- list->has_to_type = 1;
- list->to_type = OSMO_CC_TYPE_SUBSCRIBER;
- goto next_to;
- } else
- if (!strcasecmp(token, "abbreviated")) {
- list->has_to_type = 1;
- list->to_type = OSMO_CC_TYPE_ABBREVIATED;
- goto next_to;
- } else
- if (!strcasecmp(token, "allowed")) {
- if (no_present)
- goto no_present_error;
- list->has_to_present = 1;
- list->to_present = OSMO_CC_PRESENT_ALLOWED;
- goto next_to;
- } else
- if (!strcasecmp(token, "restricted")) {
- if (no_present)
- goto no_present_error;
- list->has_to_present = 1;
- list->to_present = OSMO_CC_PRESENT_RESTRICTED;
- goto next_to;
- } else {
- at_used = star_used = 0;
- for (i = j = 0; token[i] && j < (int)sizeof(list->to) - 1; i++, j++) {
- if (token[i] == '*') {
- if (star_used) {
- free(list);
- LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
- LOGP(DCC, LOGL_ERROR, "The '*' may be used only once.\n");
- return -EINVAL;
- }
- list->to[j] = SCREEN_STAR;
- star_used = 1;
- } else
- if (token[i] == '@') {
- if (!calling_in) {
- free(list);
- LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
- LOGP(DCC, LOGL_ERROR, "The '@' may be used only for incoming calls from interface.\n");
- return -EINVAL;
- }
- if (at_used) {
- free(list);
- LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
- LOGP(DCC, LOGL_ERROR, "The '@' may be used only once.\n");
- return -EINVAL;
- }
- list->to[j] = SCREEN_AT;
- at_used = 1;
- } else
- if (token[i] == '\\' && token[i + 1] != '\0')
- list->to[j] = token[++i];
- else
- list->to[j] = token[i];
- }
- list->to[j] = '\0';
- }
-
- token = osmo_cc_strtok_quotes(&text);
- if (token) {
- free(list);
- LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
- LOGP(DCC, LOGL_ERROR, "Got garbage behind screening result.\n");
- return -EINVAL;
- }
-
- /* attach screen entry to list */
- while (*list_p)
- list_p = &((*list_p)->next);
- *list_p = list;
-
- return 0;
-}
-
-void osmo_cc_flush_screen(osmo_cc_screen_list_t *list)
-{
- osmo_cc_screen_list_t *temp;
-
- while (list) {
- temp = list;
- list = list->next;
- free(temp);
- }
-}
-
-const char *print_rule_string(const char *input)
-{
- static char output[256];
- int i;
-
- for (i = 0; *input && i < (int)sizeof(output) - 1; i++, input++) {
- switch (*input) {
- case SCREEN_QUESTIONMARK:
- output[i] = '?';
- break;
- case SCREEN_STAR:
- output[i] = '*';
- break;
- case SCREEN_AT:
- output[i] = '@';
- break;
- default:
- output[i] = *input;
- }
- }
-
- output[i] = '\0';
- return output;
-}
-
-static int osmo_cc_screen(const char *what, osmo_cc_screen_list_t *list, uint8_t *type, uint8_t *present, char *id_to, int id_to_size, const char *id_from, const char **routing_p)
-{
- const char *suffix;
- int i, j, rule;
-
- LOGP(DCC, LOGL_INFO, "Screening %s '%s':\n", what, id_from);
- switch (*type) {
- case OSMO_CC_TYPE_UNKNOWN:
- LOGP(DCC, LOGL_INFO, " -> type = unknown\n");
- break;
- case OSMO_CC_TYPE_INTERNATIONAL:
- LOGP(DCC, LOGL_INFO, " -> type = international\n");
- break;
- case OSMO_CC_TYPE_NATIONAL:
- LOGP(DCC, LOGL_INFO, " -> type = national\n");
- break;
- case OSMO_CC_TYPE_NETWORK:
- LOGP(DCC, LOGL_INFO, " -> type = network\n");
- break;
- case OSMO_CC_TYPE_SUBSCRIBER:
- LOGP(DCC, LOGL_INFO, " -> type = subscriber\n");
- break;
- case OSMO_CC_TYPE_ABBREVIATED:
- LOGP(DCC, LOGL_INFO, " -> type = abbreviated\n");
- break;
- }
- if (present) switch (*present) {
- case OSMO_CC_PRESENT_ALLOWED:
- LOGP(DCC, LOGL_INFO, " -> present = allowed\n");
- break;
- case OSMO_CC_PRESENT_RESTRICTED:
- LOGP(DCC, LOGL_INFO, " -> present = restricted\n");
- break;
- }
-
- rule = 0;
- while (list) {
- rule++;
- LOGP(DCC, LOGL_INFO, "Comparing with rule #%d: '%s':\n", rule, print_rule_string(list->from));
- if (list->has_from_type) switch (list->from_type) {
- case OSMO_CC_TYPE_UNKNOWN:
- LOGP(DCC, LOGL_INFO, " -> type = unknown\n");
- break;
- case OSMO_CC_TYPE_INTERNATIONAL:
- LOGP(DCC, LOGL_INFO, " -> type = international\n");
- break;
- case OSMO_CC_TYPE_NATIONAL:
- LOGP(DCC, LOGL_INFO, " -> type = national\n");
- break;
- case OSMO_CC_TYPE_NETWORK:
- LOGP(DCC, LOGL_INFO, " -> type = network\n");
- break;
- case OSMO_CC_TYPE_SUBSCRIBER:
- LOGP(DCC, LOGL_INFO, " -> type = subscriber\n");
- break;
- case OSMO_CC_TYPE_ABBREVIATED:
- LOGP(DCC, LOGL_INFO, " -> type = abbreviated\n");
- break;
- }
- if (list->has_from_present) switch (list->from_present) {
- case OSMO_CC_PRESENT_ALLOWED:
- LOGP(DCC, LOGL_INFO, " -> present = allowed\n");
- break;
- case OSMO_CC_PRESENT_RESTRICTED:
- LOGP(DCC, LOGL_INFO, " -> present = restricted\n");
- break;
- }
- suffix = NULL;
- /* attributes do not match */
- if (list->has_from_type && list->from_type != *type) {
- LOGP(DCC, LOGL_INFO, "Rule does not match, because 'type' is different.\n");
- continue;
- }
- if (present && list->has_from_present && list->from_present != *present) {
- LOGP(DCC, LOGL_INFO, "Rule does not match, because 'present' is different.\n");
- continue;
- }
- for (i = 0; list->from[i] && id_from[i]; i++) {
- /* '?' means: any digit, so it machtes */
- if (list->from[i] == SCREEN_QUESTIONMARK) {
- continue;
- }
- /* '*' means: anything may follow, so it machtes */
- if (list->from[i] == SCREEN_STAR) {
- suffix = id_from + i;
- break;
- }
- /* check if digit doesn't matches */
- if (list->from[i] != id_from[i])
- break;
- }
- /* if last checked digit is '*', we have a match */
- /* also if we hit EOL at id_from and next check digit is '*' */
- if (list->from[i] == SCREEN_STAR)
- break;
- /* if all digits have matched */
- if (list->from[i] == '\0' && id_from[i] == '\0')
- break;
- LOGP(DCC, LOGL_INFO, "Rule does not match, because %s is different.\n", what);
- list = list->next;
- }
-
- /* if no list entry matches */
- if (!list)
- return -1;
-
- /* replace ID */
- if (list->has_to_type) {
- *type = list->to_type;
- }
- if (present && list->has_to_present) {
- *present = list->to_present;
- }
- for (i = j = 0; list->to[i]; i++) {
- if (j == id_to_size - 1)
- break;
- /* '*' means to use suffix of input string */
- if (list->to[i] == SCREEN_STAR && suffix) {
- while (*suffix) {
- id_to[j++] = *suffix++;
- if (j == id_to_size - 1)
- break;
- }
- continue;
- /* '@' means to stop and return routing also */
- } else if (list->to[i] == SCREEN_AT) {
- if (routing_p)
- *routing_p = &list->to[i + 1];
- break;
- }
- /* copy output digit */
- id_to[j++] = list->to[i];
- }
- id_to[j] = '\0';
-
- LOGP(DCC, LOGL_INFO, "Rule matches, changing %s to '%s'.\n", what, print_rule_string(id_to));
- if (list->has_to_type) switch (list->to_type) {
- case OSMO_CC_TYPE_UNKNOWN:
- LOGP(DCC, LOGL_INFO, " -> type = unknown\n");
- break;
- case OSMO_CC_TYPE_INTERNATIONAL:
- LOGP(DCC, LOGL_INFO, " -> type = international\n");
- break;
- case OSMO_CC_TYPE_NATIONAL:
- LOGP(DCC, LOGL_INFO, " -> type = national\n");
- break;
- case OSMO_CC_TYPE_NETWORK:
- LOGP(DCC, LOGL_INFO, " -> type = network\n");
- break;
- case OSMO_CC_TYPE_SUBSCRIBER:
- LOGP(DCC, LOGL_INFO, " -> type = subscriber\n");
- break;
- case OSMO_CC_TYPE_ABBREVIATED:
- LOGP(DCC, LOGL_INFO, " -> type = abbreviated\n");
- break;
- }
- if (list->has_to_present) switch (list->to_present) {
- case OSMO_CC_PRESENT_ALLOWED:
- LOGP(DCC, LOGL_INFO, " -> present = allowed\n");
- break;
- case OSMO_CC_PRESENT_RESTRICTED:
- LOGP(DCC, LOGL_INFO, " -> present = restricted\n");
- break;
- }
- if (routing_p && *routing_p)
- LOGP(DCC, LOGL_INFO, " -> remote = %s\n", *routing_p);
-
- return 0;
-}
-
-osmo_cc_msg_t *osmo_cc_screen_msg(osmo_cc_endpoint_t *ep, osmo_cc_msg_t *old_msg, int in, const char **routing_p)
-{
- osmo_cc_msg_t *new_msg;
- char id[256], calling[256], called[256], redir[256];
- uint8_t calling_type, calling_plan, calling_present, calling_screen;
- uint8_t called_type, called_plan;
- uint8_t redir_type, redir_plan, redir_present, redir_screen, redir_reason;
- int calling_status = 0, called_status = 0, redir_status = 0;
- int rc;
- void *ie, *to_ie;
- uint8_t ie_type;
- uint16_t ie_length;
- void *ie_value;
-
- if (in && ep->screen_calling_in) {
- rc = osmo_cc_get_ie_calling(old_msg, 0, &calling_type, &calling_plan, &calling_present, &calling_screen, id, sizeof(id));
- if (rc >= 0) {
- rc = osmo_cc_screen("incoming caller ID", ep->screen_calling_in, &calling_type, &calling_present, calling, sizeof(calling), id, routing_p);
- if (rc >= 0)
- calling_status = 1;
- } else {
- calling_type = OSMO_CC_TYPE_UNKNOWN;
- calling_plan = OSMO_CC_PLAN_TELEPHONY;
- calling_present = OSMO_CC_PRESENT_ALLOWED;
- calling_screen = OSMO_CC_SCREEN_NETWORK;
- rc = osmo_cc_screen("incoming caller ID", ep->screen_calling_in, &calling_type, &calling_present, calling, sizeof(calling), "", routing_p);
- if (rc >= 0)
- calling_status = 1;
- }
- rc = osmo_cc_get_ie_redir(old_msg, 0, &redir_type, &redir_plan, &redir_present, &redir_screen, &redir_reason, id, sizeof(id));
- if (rc >= 0) {
- rc = osmo_cc_screen("incoming redirecting number", ep->screen_calling_in, &redir_type, &redir_present, redir, sizeof(redir), id, NULL);
- if (rc >= 0)
- redir_status = 1;
- }
- }
- if (in && ep->screen_called_in) {
- rc = osmo_cc_get_ie_called(old_msg, 0, &called_type, &called_plan, id, sizeof(id));
- if (rc >= 0) {
- rc = osmo_cc_screen("incoming dialed number", ep->screen_called_in, &called_type, NULL, called, sizeof(called), id, routing_p);
- if (rc >= 0)
- called_status = 1;
- } else {
- called_type = OSMO_CC_TYPE_UNKNOWN;
- called_plan = OSMO_CC_PLAN_TELEPHONY;
- rc = osmo_cc_screen("incoming dialed number", ep->screen_called_in, &called_type, NULL, called, sizeof(called), "", routing_p);
- if (rc >= 0)
- called_status = 1;
- }
- }
- if (!in && ep->screen_calling_out) {
- rc = osmo_cc_get_ie_calling(old_msg, 0, &calling_type, &calling_plan, &calling_present, &calling_screen, id, sizeof(id));
- if (rc >= 0) {
- rc = osmo_cc_screen("outgoing caller ID", ep->screen_calling_out, &calling_type, &calling_present, calling, sizeof(calling), id, NULL);
- if (rc >= 0)
- calling_status = 1;
- } else {
- calling_type = OSMO_CC_TYPE_UNKNOWN;
- calling_plan = OSMO_CC_PLAN_TELEPHONY;
- calling_present = OSMO_CC_PRESENT_ALLOWED;
- calling_screen = OSMO_CC_SCREEN_NETWORK;
- rc = osmo_cc_screen("outgoing caller ID", ep->screen_calling_out, &calling_type, &calling_present, calling, sizeof(calling), "", NULL);
- if (rc >= 0)
- calling_status = 1;
- }
- rc = osmo_cc_get_ie_redir(old_msg, 0, &redir_type, &redir_plan, &redir_present, &redir_screen, &redir_reason, id, sizeof(id));
- if (rc >= 0) {
- rc = osmo_cc_screen("outgoing redirecting number", ep->screen_calling_out, &redir_type, &redir_present, redir, sizeof(redir), id, NULL);
- if (rc >= 0)
- redir_status = 1;
- }
- }
- if (!in && ep->screen_called_out) {
- rc = osmo_cc_get_ie_called(old_msg, 0, &called_type, &called_plan, id, sizeof(id));
- if (rc >= 0) {
- rc = osmo_cc_screen("outgoing dialed number", ep->screen_called_out, &called_type, NULL, called, sizeof(called), id, NULL);
- if (rc >= 0)
- called_status = 1;
- } else {
- called_type = OSMO_CC_TYPE_UNKNOWN;
- called_plan = OSMO_CC_PLAN_TELEPHONY;
- rc = osmo_cc_screen("outgoing dialed number", ep->screen_called_out, &called_type, NULL, called, sizeof(called), "", NULL);
- if (rc >= 0)
- called_status = 1;
- }
- }
-
- /* nothing screened */
- if (!calling_status && !called_status && !redir_status)
- return old_msg;
-
- new_msg = osmo_cc_new_msg(old_msg->type);
-
- /* copy and replace */
- ie = old_msg->data;
- while ((ie_value = osmo_cc_msg_sep_ie(old_msg, &ie, &ie_type, &ie_length))) {
- switch (ie_type) {
- case OSMO_CC_IE_CALLING:
- if (calling_status) {
- osmo_cc_add_ie_calling(new_msg, calling_type, calling_plan, calling_present, calling_screen, calling);
- calling_status = 0;
- break;
- }
- goto copy;
- case OSMO_CC_IE_CALLED:
- if (called_status) {
- osmo_cc_add_ie_called(new_msg, called_type, called_plan, called);
- called_status = 0;
- break;
- }
- goto copy;
- case OSMO_CC_IE_REDIR:
- if (redir_status) {
- osmo_cc_add_ie_redir(new_msg, redir_type, redir_plan, redir_present, redir_screen, redir_reason, redir);
- redir_status = 0;
- break;
- }
- goto copy;
- default:
- copy:
- to_ie = osmo_cc_add_ie(new_msg, ie_type, ie_length);
- memcpy(to_ie, ie_value, ie_length);
- }
- }
-
- /* applend, if not yet in message (except redir, since it must exist) */
- if (calling_status)
- osmo_cc_add_ie_calling(new_msg, calling_type, calling_plan, calling_present, calling_screen, calling);
- if (called_status)
- osmo_cc_add_ie_called(new_msg, called_type, called_plan, called);
-
- free(old_msg);
- return new_msg;
-}
-