| /* Trunk handling */ |
| |
| /* |
| * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org> |
| * (C) 2009-2012 by On-Waves |
| * (C) 2017-2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> |
| * All Rights Reserved |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU Affero 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 Affero General Public License for more details. |
| * |
| * You should have received a copy of the GNU Affero General Public License |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| * |
| */ |
| |
| #include <osmocom/mgcp/mgcp_internal.h> |
| #include <osmocom/mgcp/mgcp_endp.h> |
| #include <osmocom/mgcp/mgcp_trunk.h> |
| |
| /*! allocate trunk and add it (if required) to the trunk list. |
| * (called once at startup by VTY). |
| * \param[in] cfg mgcp configuration. |
| * \param[in] ttype trunk type. |
| * \param[in] nr trunk number. |
| * \returns pointer to allocated trunk, NULL on failure. */ |
| struct mgcp_trunk *mgcp_trunk_alloc(struct mgcp_config *cfg, enum mgcp_trunk_type ttype, int nr) |
| { |
| struct mgcp_trunk *trunk; |
| |
| trunk = talloc_zero(cfg, struct mgcp_trunk); |
| if (!trunk) { |
| LOGP(DLMGCP, LOGL_ERROR, "Failed to allocate.\n"); |
| return NULL; |
| } |
| |
| trunk->cfg = cfg; |
| trunk->trunk_type = ttype; |
| trunk->trunk_nr = nr; |
| |
| trunk->audio_send_ptime = 1; |
| trunk->audio_send_name = 1; |
| trunk->vty_number_endpoints = 33; |
| trunk->omit_rtcp = 0; |
| |
| mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE); |
| |
| llist_add_tail(&trunk->entry, &cfg->trunks); |
| |
| mgcp_ratectr_trunk_alloc(cfg, &trunk->ratectr); |
| |
| return trunk; |
| } |
| |
| /*! allocate endpoints and set default values |
| * (called once at startup by VTY). |
| * \param[in] trunk trunk configuration. |
| * \returns 0 on success, -1 on failure. */ |
| int mgcp_trunk_alloc_endpts(struct mgcp_trunk *trunk) |
| { |
| int i; |
| struct mgcp_endpoint *endp; |
| |
| /* Make sure the amount of requested endpoints does not execeed |
| * sane limits. The VTY already limits the possible amount, |
| * however miss-initalation of the struct or memory corruption |
| * could still lead to an excessive allocation of endpoints, so |
| * better stop early if that is the case. */ |
| OSMO_ASSERT(trunk->vty_number_endpoints < 65534); |
| |
| /* This function is called once on startup by the VTY to allocate the |
| * endpoints. The number of endpoints must not change througout the |
| * runtime of the MGW */ |
| OSMO_ASSERT(trunk->number_endpoints == 0); |
| OSMO_ASSERT(trunk->endpoints == NULL); |
| |
| /* allocate pointer array for the endpoints */ |
| trunk->endpoints = _talloc_zero_array(trunk->cfg, |
| sizeof(struct mgcp_endpoint *), trunk->vty_number_endpoints, "endpoints"); |
| if (!trunk->endpoints) |
| return -1; |
| |
| /* create endpoints */ |
| for (i = 0; i < trunk->vty_number_endpoints; ++i) { |
| endp = mgcp_endp_alloc(trunk, i); |
| if (!endp) { |
| talloc_free(trunk->endpoints); |
| return -1; |
| } |
| trunk->endpoints[i] = endp; |
| } |
| |
| /* make the endpoints we just created available to the MGW code */ |
| trunk->number_endpoints = trunk->vty_number_endpoints; |
| |
| return 0; |
| } |
| |
| /*! get trunk configuration by trunk number (index). |
| * \param[in] cfg mgcp configuration. |
| * \param[in] index trunk number. |
| * \returns pointer to trunk configuration, NULL on error. */ |
| struct mgcp_trunk *mgcp_trunk_by_num(const struct mgcp_config *cfg, int index) |
| { |
| struct mgcp_trunk *trunk; |
| |
| llist_for_each_entry(trunk, &cfg->trunks, entry) |
| if (trunk->trunk_nr == index) |
| return trunk; |
| |
| return NULL; |
| } |
| |
| /*! Find a trunk by the trunk prefix in the endpoint name. |
| * \param[in] epname endpoint name with trunk prefix to look up. |
| * \param[in] cfg that contains the trunks where the endpoint is located. |
| * \returns trunk or NULL if trunk was not found. */ |
| struct mgcp_trunk *mgcp_trunk_by_name(const struct mgcp_config *cfg, const char *epname) |
| { |
| size_t prefix_len; |
| char epname_lc[MGCP_ENDPOINT_MAXLEN]; |
| |
| osmo_str_tolower_buf(epname_lc, sizeof(epname_lc), epname); |
| epname = epname_lc; |
| |
| prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK) - 1; |
| if (strncmp(epname, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, prefix_len) == 0) { |
| return mgcp_trunk_by_num(cfg, MGCP_VIRT_TRUNK_ID); |
| } |
| |
| /* E1 trunks are not implemented yet, so we deny any request for an |
| * e1 trunk for now. */ |
| prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_E1_TRUNK) - 1; |
| if (strncmp(epname, MGCP_ENDPOINT_PREFIX_E1_TRUNK, prefix_len) == 0) { |
| LOGP(DLMGCP, LOGL_ERROR, |
| "endpoint name \"%s\" suggests an E1 trunk, but E1 trunks are not implemented in this version of osmo-mgw!\n", epname); |
| return NULL; |
| } |
| |
| /* Earlier versions of osmo-mgw were accepting endpoint names |
| * without trunk prefix. This is normally not allowed, each MGCP |
| * request should supply an endpoint name with trunk prefix. |
| * However in order to stay compatible with old versions of |
| * osmo-bsc and osmo-msc we still accept endpoint names without |
| * trunk prefix and just assume that the virtual trunk should |
| * be selected. There is even a TTCN3 test for this, see also: |
| * MGCP_Test.TC_crcx_noprefix */ |
| if ((epname[0] >= '0' && epname[0] <= '9') || (epname[0] >= 'a' && epname[0] <= 'f')) { |
| LOGP(DLMGCP, LOGL_ERROR, "missing trunk prefix in endpoint name \"%s\", assuming trunk \"%s\"!\n", epname, |
| MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK); |
| return mgcp_trunk_by_num(cfg, MGCP_VIRT_TRUNK_ID); |
| } |
| |
| LOGP(DLMGCP, LOGL_ERROR, "unable to find trunk for endpoint name \"%s\"!\n", epname); |
| return NULL; |
| } |