blob: 024db039d32c29572198aa526cccf182237367d5 [file] [log] [blame]
Philipp Maierc66ab2c2020-06-02 20:55:34 +02001/* Trunk handling */
2
3/*
4 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
5 * (C) 2009-2012 by On-Waves
6 * (C) 2017-2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
18 *
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <osmocom/mgcp/mgcp_internal.h>
25#include <osmocom/mgcp/mgcp_endp.h>
26#include <osmocom/mgcp/mgcp_trunk.h>
27
Philipp Maierbce5f292020-06-18 11:57:17 +020028/*! allocate trunk and add it (if required) to the trunk list.
29 * (called once at startup by VTY).
30 * \param[in] cfg mgcp configuration.
31 * \param[in] nr trunk number.
32 * \param[in] ttype trunk type.
33 * \returns pointer to allocated trunk, NULL on failure. */
Philipp Maierc66ab2c2020-06-02 20:55:34 +020034struct mgcp_trunk *mgcp_trunk_alloc(struct mgcp_config *cfg, enum mgcp_trunk_type ttype, int nr)
35{
36 struct mgcp_trunk *trunk;
37
38 trunk = talloc_zero(cfg, struct mgcp_trunk);
39 if (!trunk) {
40 LOGP(DLMGCP, LOGL_ERROR, "Failed to allocate.\n");
41 return NULL;
42 }
43
44 trunk->cfg = cfg;
45 trunk->trunk_type = ttype;
46 trunk->trunk_nr = nr;
47
48 trunk->audio_send_ptime = 1;
49 trunk->audio_send_name = 1;
50 trunk->vty_number_endpoints = 33;
51 trunk->omit_rtcp = 0;
52
53 mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
54
55 /* Note: Trunk Nr.0 is reserved as "virtual trunk",
56 * it is not stored using a separate pointer and
57 * not in the trunk list. */
58 if (nr > 0)
59 llist_add_tail(&trunk->entry, &cfg->trunks);
60
61 mgcp_ratectr_trunk_alloc(cfg, &trunk->ratectr);
62
63 return trunk;
64}
65
Philipp Maierbce5f292020-06-18 11:57:17 +020066/*! allocate endpoints and set default values
67 * (called once at startup by VTY).
68 * \param[in] trunk trunk configuration.
69 * \returns 0 on success, -1 on failure. */
Philipp Maierc66ab2c2020-06-02 20:55:34 +020070int mgcp_trunk_alloc_endpts(struct mgcp_trunk *trunk)
71{
72 int i;
73 char ep_name_buf[MGCP_ENDPOINT_MAXLEN];
74 struct mgcp_endpoint *endp;
75
76 /* Make sure the amount of requested endpoints does not execeed
77 * sane limits. The VTY already limits the possible amount,
78 * however miss-initalation of the struct or memory corruption
79 * could still lead to an excessive allocation of endpoints, so
80 * better stop early if that is the case. */
81 OSMO_ASSERT(trunk->vty_number_endpoints < 65534);
82
83 /* This function is called once on startup by the VTY to allocate the
84 * endpoints. The number of endpoints must not change througout the
85 * runtime of the MGW */
86 OSMO_ASSERT(trunk->number_endpoints == 0);
87 OSMO_ASSERT(trunk->endpoints == NULL);
88
89 /* allocate pointer array for the endpoints */
90 trunk->endpoints = _talloc_zero_array(trunk->cfg,
91 sizeof(struct mgcp_endpoint *), trunk->vty_number_endpoints, "endpoints");
92 if (!trunk->endpoints)
93 return -1;
94
95 /* create endpoints */
96 for (i = 0; i < trunk->vty_number_endpoints; ++i) {
97 switch (trunk->trunk_type) {
98 case MGCP_TRUNK_VIRTUAL:
99 snprintf(ep_name_buf, sizeof(ep_name_buf), "%s%x@%s", MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, i,
100 trunk->cfg->domain);
101 break;
102 case MGCP_TRUNK_E1:
103 /* FIXME: E1 trunk implementation is work in progress, this endpoint
104 * name is incomplete (subslots) */
105 snprintf(ep_name_buf, sizeof(ep_name_buf), "%s-1/%x", MGCP_ENDPOINT_PREFIX_E1_TRUNK, i);
106 break;
107 default:
108 osmo_panic("Cannot allocate unimplemented trunk type %d! %s:%d\n",
109 trunk->trunk_type, __FILE__, __LINE__);
110 }
111
112 endp = mgcp_endp_alloc(trunk, ep_name_buf);
113 if (!endp) {
114 talloc_free(trunk->endpoints);
115 return -1;
116 }
117 trunk->endpoints[i] = endp;
118 }
119
120 /* make the endpoints we just created available to the MGW code */
121 trunk->number_endpoints = trunk->vty_number_endpoints;
122
123 return 0;
124}
125
126/*! get trunk configuration by trunk number (index).
Philipp Maierbce5f292020-06-18 11:57:17 +0200127 * \param[in] cfg mgcp configuration.
128 * \param[in] index trunk number.
129 * \returns pointer to trunk configuration, NULL on error. */
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200130struct mgcp_trunk *mgcp_trunk_by_num(const struct mgcp_config *cfg, int index)
131{
132 struct mgcp_trunk *trunk;
133
134 llist_for_each_entry(trunk, &cfg->trunks, entry)
135 if (trunk->trunk_nr == index)
136 return trunk;
137
138 return NULL;
139}
140
141/*! Find a trunk by the trunk prefix in the endpoint name.
142 * \param[in] epname endpoint name with trunk prefix to look up.
143 * \param[in] cfg that contains the trunks where the endpoint is located.
144 * \returns trunk or NULL if trunk was not found. */
145struct mgcp_trunk *mgcp_trunk_by_name(const struct mgcp_config *cfg, const char *epname)
146{
147 size_t prefix_len;
148 char epname_lc[MGCP_ENDPOINT_MAXLEN];
149
150 osmo_str_tolower_buf(epname_lc, sizeof(epname_lc), epname);
151 epname = epname_lc;
152
153 prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK) - 1;
154 if (strncmp(epname, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, prefix_len) == 0) {
155 return cfg->virt_trunk;
156 }
157
158 /* E1 trunks are not implemented yet, so we deny any request for an
159 * e1 trunk for now. */
160 prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_E1_TRUNK) - 1;
161 if (strncmp(epname, MGCP_ENDPOINT_PREFIX_E1_TRUNK, prefix_len) == 0) {
162 LOGP(DLMGCP, LOGL_ERROR,
163 "endpoint name \"%s\" suggests an E1 trunk, but E1 trunks are not implemented in this version of osmo-mgw!\n", epname);
164 return NULL;
165 }
166
167 /* Earlier versions of osmo-mgw were accepting endpoint names
168 * without trunk prefix. This is normally not allowed, each MGCP
169 * request should supply an endpoint name with trunk prefix.
170 * However in order to stay compatible with old versions of
171 * osmo-bsc and osmo-msc we still accept endpoint names without
172 * trunk prefix and just assume that the virtual trunk should
173 * be selected. There is even a TTCN3 test for this, see also:
174 * MGCP_Test.TC_crcx_noprefix */
175 if ((epname[0] >= '0' && epname[0] <= '9') || (epname[0] >= 'a' && epname[0] <= 'f')) {
176 LOGP(DLMGCP, LOGL_ERROR, "missing trunk prefix in endpoint name \"%s\", assuming trunk \"%s\"!\n", epname,
177 MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK);
178 return cfg->virt_trunk;
179 }
180
181 LOGP(DLMGCP, LOGL_ERROR, "unable to find trunk for endpoint name \"%s\"!\n", epname);
182 return NULL;
183}