diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2021-08-25 15:44:03 +0200 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2021-09-17 16:33:29 +0200 |
commit | 67d66e73d233e156aa7dddab2d56c0bb2211c02e (patch) | |
tree | f25123db95a5c2cc70f05f4e85d7c8902d3c50f8 /src/router/routing.c | |
parent | 42f4d661a999215166672fba9d3a182ae58babcc (diff) |
Diffstat (limited to 'src/router/routing.c')
-rw-r--r-- | src/router/routing.c | 261 |
1 files changed, 195 insertions, 66 deletions
diff --git a/src/router/routing.c b/src/router/routing.c index b49f6d4..8d5485c 100644 --- a/src/router/routing.c +++ b/src/router/routing.c @@ -34,141 +34,270 @@ extern char **environ; -static const char *env_int(const char *name, int value) +static struct env { + int coding, capability, mode; + + int type, plan, present, screen, reason; + char *number; + + int network_type; + char *network_id; + + int complete; +} env; + +struct env_def { + const char *n; + char **s; + int *i; + const char *d; + const char *(*value2name)(int value); + int num; +} env_def[] = { + { .n = "BEARER_CODING", .i = &env.coding, .d = "coding of bearer capability", .value2name = osmo_cc_coding_value2name, .num = OSMO_CC_CODING_NUM }, + { .n = "BEARER_CAPABILITY", .i = &env.capability, .d = "bearer capability", .value2name = osmo_cc_capability_value2name, .num = OSMO_CC_CAPABILITY_NUM }, + { .n = "BEARER_MODE", .i = &env.mode, .d = "mode of bearer", .value2name = osmo_cc_mode_value2name, .num = OSMO_CC_MODE_NUM }, + + { .n = "CALLING_TYPE", .i = &env.type, .d = "type of calling number", .value2name = osmo_cc_type_value2name, .num = OSMO_CC_TYPE_NUM }, + { .n = "CALLING_PLAN", .i = &env.plan, .d = "numbering plan of calling number", .value2name = osmo_cc_plan_value2name, .num = OSMO_CC_PLAN_NUM }, + { .n = "CALLING_PRESENT", .i = &env.present, .d = "presentation of calling number", .value2name = osmo_cc_present_value2name, .num = OSMO_CC_PRESENT_NUM }, + { .n = "CALLING_SCREEN", .i = &env.screen, .d = "screen of calling number", .value2name = osmo_cc_screen_value2name, .num = OSMO_CC_SCREEN_NUM }, + { .n = "CALLING", .s = &env.number, .d = "calling number" }, + { .n = "CALLING_INTERFACE", .s = &env.number, .d = "calling interface name" }, + + { .n = "CALLING2_TYPE", .i = &env.type, .d = "type of second calling number", .value2name = osmo_cc_type_value2name, .num = OSMO_CC_TYPE_NUM }, + { .n = "CALLING2_PLAN", .i = &env.plan, .d = "numbering plan of awxons calling number", .value2name = osmo_cc_plan_value2name, .num = OSMO_CC_PLAN_NUM}, + { .n = "CALLING2_PRESENT", .i = &env.present, .d = "presentation of second calling number", .value2name = osmo_cc_present_value2name, .num = OSMO_CC_PRESENT_NUM }, + { .n = "CALLING2_SCREEN", .i = &env.screen, .d = "screen of second calling number", .value2name = osmo_cc_screen_value2name, .num = OSMO_CC_SCREEN_NUM }, + { .n = "CALLING2", .s = &env.number, .d = "second calling number" }, + + { .n = "NETWORK_TYPE", .i = &env.network_type, .d = "type of calling network" }, + { .n = "NETWORK_ID", .s = &env.network_id, .d = "id of subscriber at calling network" }, + + { .n = "REDIRECTING_TYPE", .i = &env.type, .d = "type of redirecting number", .value2name = osmo_cc_type_value2name, .num = OSMO_CC_TYPE_NUM }, + { .n = "REDIRECTING_PLAN", .i = &env.plan, .d = "numbering plan of redirecting number", .value2name = osmo_cc_plan_value2name, .num = OSMO_CC_PLAN_NUM }, + { .n = "REDIRECTING_PRESENT", .i = &env.present, .d = "presentation of redirecting number", .value2name = osmo_cc_present_value2name, .num = OSMO_CC_PRESENT_NUM }, + { .n = "REDIRECTING_SCREEN", .i = &env.screen, .d = "screen of redirecting number", .value2name = osmo_cc_screen_value2name, .num = OSMO_CC_SCREEN_NUM }, + { .n = "REDIRECTING_REASON", .i = &env.reason, .d = "reason for redirecting", .value2name = osmo_cc_redir_reason_value2name, .num = OSMO_CC_REDIR_REASON_NUM }, + { .n = "REDIRECTING", .s = &env.number, .d = "redirecting number" }, + + { .n = "DIALING_TYPE", .i = &env.type, .d = "type of dialing number", .value2name = osmo_cc_type_value2name, .num = OSMO_CC_TYPE_NUM }, + { .n = "DIALING_PLAN", .i = &env.plan, .d = "numbering plan of dialing number", .value2name = osmo_cc_plan_value2name, .num = OSMO_CC_PLAN_NUM }, + { .n = "DIALING", .s = &env.number, .d = "dialing number" }, + { .n = "KEYPAD", .s = &env.number, .d = "keypad dialing (May be uses for special ISDN applications.)" }, + + { .n = "COMPLETE", .i = &env.complete, .d = "set to '1' if dialing is a complete number" }, + + { .n = NULL } +}; + +static int env_set(routing_t *routing, const char *name, int index) { - char *string = malloc(strlen(name) + 20); + int i; - sprintf(string, "CC_%s=%d", name, value); - - return string; -} + for (i = 0; env_def[i].n; i++) { + if (!strcmp(env_def[i].n, name)) + break; + } + if (!env_def[i].n) { + PDEBUG(DROUTER, DEBUG_ERROR, "Software error: Environment variable '%s' does not exist in definition, please fix!\n", name); + return index; + } -static const char *env_string(const char *name, const char *value) -{ - char *string = malloc(strlen(name) + strlen(value) + 8); + if (env_def[i].s) { + char *string = malloc(strlen(name) + strlen(*env_def[i].s) + 8); + sprintf(string, "CC_%s=%s", name, *env_def[i].s); + routing->envp[index++] = string; + } - sprintf(string, "CC_%s=%s", name, value); + if (env_def[i].i) { + char *string = malloc(strlen(name) + 30); + sprintf(string, "CC_%s=%d", name, *env_def[i].i); + routing->envp[index++] = string; + if (env_def[i].value2name && env_def[i].value2name(*env_def[i].i)[0] != '<') { + char *string = malloc(strlen(name) + strlen(env_def[i].value2name(*env_def[i].i)) + 16); + sprintf(string, "CC_%s_NAME=%s", name, env_def[i].value2name(*env_def[i].i)); + routing->envp[index++] = string; + } + } - return string; + return index; } -static void enqueue_string(struct string_queue **queue_p, const char *string, const char *suffix) +static void env_add(routing_t *routing, const char *name) { - struct string_queue *queue; - - queue = calloc(1, sizeof(*queue)); - queue->string = malloc(strlen(string) + strlen(suffix) + 1); - strcpy(queue->string, string); - strcat(queue->string, suffix); - - while (*queue_p) - queue_p = &((*queue_p)->next); - *queue_p = queue; + routing->envc = env_set(routing, name, routing->envc); } -static char *dequeue_string(struct string_queue **queue_p) +void env_help(void) { - struct string_queue *queue = *queue_p; - char *string; - - if (!queue) - return NULL; - - string = queue->string; - *queue_p = queue->next; - free(queue); - - return string; + int i; + + printf("Available environment variables:\n\n"); + for (i = 0; env_def[i].n; i++) { + printf("Variable: CC_%s\n", env_def[i].n); + printf(" Description: %s\n", env_def[i].d); + if (env_def[i].value2name) { + printf(" Additional variable: CC_%s_NAME\n", env_def[i].n); + } + } } /* prepare environment with setup info */ void routing_env_msg(routing_t *routing, osmo_cc_msg_t *msg) { + int rc, i; uint8_t coding, capability, mode; uint8_t type, plan, present, screen, reason; + char number[256]; uint8_t network_type; - char number[256], network_id[256]; - int rc, i; + char network_id[256]; for (i = 0; environ[i]; i++) { routing->envp[routing->envc++] = strdup(environ[i]); } + memset(&env, 0, sizeof(env)); + rc = osmo_cc_get_ie_bearer(msg, 0, &coding, &capability, &mode); if (rc >= 0) { - routing->envp[routing->envc++] = env_int("BEARER_CODING", coding); - routing->envp[routing->envc++] = env_int("BEARER_CAPABILITY", capability); - routing->envp[routing->envc++] = env_int("BEARER_MODE", mode); + env.coding = coding; + env.capability = capability; + env.mode = mode; + env_add(routing, "BEARER_CODING"); + env_add(routing, "BEARER_CAPABILITY"); + env_add(routing, "BEARER_MODE"); } rc = osmo_cc_get_ie_calling(msg, 0, &type, &plan, &present, &screen, number, sizeof(number)); if (rc >= 0) { - routing->envp[routing->envc++] = env_int("CALLING_TYPE", type); - routing->envp[routing->envc++] = env_int("CALLING_PLAN", plan); - routing->envp[routing->envc++] = env_int("CALLING_PRESENT", present); - routing->envp[routing->envc++] = env_int("CALLING_SCREEN", screen); - routing->envp[routing->envc++] = env_string("CALLING", number); + env.type = type; + env.plan = plan; + env.present = present; + env.screen = screen; + env.number = number; + env_add(routing, "CALLING_TYPE"); + env_add(routing, "CALLING_PLAN"); + env_add(routing, "CALLING_PRESENT"); + env_add(routing, "CALLING_SCREEN"); + env_add(routing, "CALLING"); } rc = osmo_cc_get_ie_calling_interface(msg, 0, number, sizeof(number)); if (rc >= 0) { - routing->envp[routing->envc++] = env_string("CALLING_INTERFACE", number); + env.number = number; + env_add(routing, "CALLING_INTERFACE"); } rc = osmo_cc_get_ie_calling(msg, 1, &type, &plan, &present, &screen, number, sizeof(number)); if (rc >= 0) { - routing->envp[routing->envc++] = env_int("CALLING2_TYPE", type); - routing->envp[routing->envc++] = env_int("CALLING2_PLAN", plan); - routing->envp[routing->envc++] = env_int("CALLING2_PRESENT", present); - routing->envp[routing->envc++] = env_int("CALLING2_SCREEN", screen); - routing->envp[routing->envc++] = env_string("CALLING2", number); + env.type = type; + env.plan = plan; + env.present = present; + env.screen = screen; + env.number = number; + env_add(routing, "CALLING2_TYPE"); + env_add(routing, "CALLING2_PLAN"); + env_add(routing, "CALLING2_PRESENT"); + env_add(routing, "CALLING2_SCREEN"); + env_add(routing, "CALLING2"); } rc = osmo_cc_get_ie_calling_network(msg, 0, &network_type, network_id, sizeof(network_id)); if (rc >= 0) { - routing->envp[routing->envc++] = env_string("NETWORK_TYPE", osmo_cc_network_type_name(network_type)); - routing->envp[routing->envc++] = env_string("NETWORK_ID", network_id); + env.network_type = network_type; + env.network_id = network_id; + env_add(routing, "NETWORK_TYPE"); + env_add(routing, "NETWORK_ID"); } rc = osmo_cc_get_ie_redir(msg, 0, &type, &plan, &present, &screen, &reason, number, sizeof(number)); if (rc >= 0) { - routing->envp[routing->envc++] = env_int("REDIRECTING_TYPE", type); - routing->envp[routing->envc++] = env_int("REDIRECTING_PLAN", plan); - routing->envp[routing->envc++] = env_int("REDIRECTING_PRESENT", present); - routing->envp[routing->envc++] = env_int("REDIRECTING_SCREEN", screen); - routing->envp[routing->envc++] = env_int("REDIRECTING_REASON", reason); - routing->envp[routing->envc++] = env_string("REDIRECTING", number); + env.type = type; + env.plan = plan; + env.present = present; + env.screen = screen; + env.reason = reason; + env.number = number; + env_add(routing, "REDIRECTING_TYPE"); + env_add(routing, "REDIRECTING_PLAN"); + env_add(routing, "REDIRECTING_PRESENT"); + env_add(routing, "REDIRECTING_SCREEN"); + env_add(routing, "REDIRECTING_REASON"); + env_add(routing, "REDIRECTING"); } rc = osmo_cc_get_ie_called(msg, 0, &type, &plan, number, sizeof(number)); if (rc >= 0) { - routing->envp[routing->envc++] = env_int("DIALING_TYPE", type); - routing->envp[routing->envc++] = env_int("DIALING_PLAN", plan); + env.type = type; + env.plan = plan; + env_add(routing, "DIALING_TYPE"); + env_add(routing, "DIALING_PLAN"); } else number[0] = 0; /* variable must always be present, so it can be updated when overlap dialing */ routing->envc_dialing = routing->envc; - routing->envp[routing->envc++] = env_string("DIALING", number); + env.number = number; + env_add(routing, "DIALING"); rc = osmo_cc_get_ie_keypad(msg, 0, number, sizeof(number)); if (rc < 0) number[0] = 0; /* variable must always be present, so it can be updated when overlap dialing */ routing->envc_keypad = routing->envc; - routing->envp[routing->envc++] = env_string("KEYPAD", number); + env.number = number; + env_add(routing, "KEYPAD"); rc = osmo_cc_get_ie_complete(msg, 0); if (rc >= 0) - routing->envp[routing->envc++] = env_int("COMPLETE", 1); + env.complete = 1; + /* variable must always be present, so it can be updated when overlap dialing */ + routing->envc_complete = routing->envc; + env_add(routing, "COMPLETE"); routing->envp[routing->envc++] = NULL; } /* update environment with info message */ -void routing_env_dialing(routing_t *routing, const char *number, const char *keypad) +void routing_env_dialing(routing_t *routing, char *number, char *keypad, int complete) { free((char *)routing->envp[routing->envc_dialing]); - routing->envp[routing->envc_dialing] = env_string("DIALING", number); + env.number = number; + env_set(routing, "DIALING", routing->envc_dialing); free((char *)routing->envp[routing->envc_keypad]); - routing->envp[routing->envc_keypad] = env_string("KEYPAD", keypad); + env.number = keypad; + env_set(routing, "KEYPAD", routing->envc_keypad); + + free((char *)routing->envp[routing->envc_complete]); + env.complete = complete; + env_set(routing, "COMPLETE", routing->envc_complete); +} + +static void enqueue_string(struct string_queue **queue_p, const char *string, const char *suffix) +{ + struct string_queue *queue; + + queue = calloc(1, sizeof(*queue)); + queue->string = malloc(strlen(string) + strlen(suffix) + 1); + strcpy(queue->string, string); + strcat(queue->string, suffix); + + while (*queue_p) + queue_p = &((*queue_p)->next); + *queue_p = queue; +} + +static char *dequeue_string(struct string_queue **queue_p) +{ + struct string_queue *queue = *queue_p; + char *string; + + if (!queue) + return NULL; + + string = queue->string; + *queue_p = queue->next; + free(queue); + + return string; } void routing_env_free(routing_t *routing) |